diff --git a/readme.md b/readme.md index df9ea36..f8d9ebc 100644 --- a/readme.md +++ b/readme.md @@ -150,31 +150,31 @@ Handle project workflows in a unified way: #### Latest -| os | https | up ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | gource | ffmpeg | -|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:|-----:|-------:| -| Arch 20240818 | ☑ | ☑ | 3.12 | 12.0 | 1.2023.13 | 0.10 | 2.1.8 | 3.8 | 0.54 | 7.0.2 | -| Alpine 3.20 | ☑ | ☐ | 3.12 | 9.0 | 1.2024.4 | 0.10 | 2.1.8 | 3.8 | 0.54 | 6.1.1 | -| Fedora 40 | ☑ | ☑ | 3.12 → 3.13 | 9.0 | 1.2024.6 | 0.9 | 2.1.6 | 3.7 | 0.55 | 6.1.2 | -| Debian Bookworm | ☐ | ☐ | 3.11 | 2.42 | 1.2020.2 | 0.9 | 2.1.8 | 3.6 | 0.54 | 5.1.6 | -| OpenSUSE 15.6 | ☐ | ☑ | 3.6 → 3.12 | 2.48 | 1.2020.9 | 0.8 | 2.1.6 | 3.5 | 0.54 | 4.4.4 | -| Ubuntu Noble | ☐ | ☐ | 3.12 | u2.42 | u1.2020.2 | u0.9 | 2.1.8 | u3.8 | 0.54 | 6.1.1 | -| Alma / Rocky 9 | ☑ | ☑ | 3.9 → 3.12 | 2.44 | e1.2024.6 | e0.8 | | | | e5.1.4 | +| os | https | updt-ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | +|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:| +| Arch 20240818 | ☑ | ☑ | 3.12 | 12.0 | 1.2023.13 | 0.10 | 2.1.8 | 3.8 | +| Alpine 3.20 | ☑ | ☐ | 3.12 | 9.0 | 1.2024.4 | 0.10 | 2.1.8 | 3.8 | +| Fedora 40 | ☑ | ☑ | 3.12 → 3.13 | 9.0 | 1.2024.6 | 0.9 | 2.1.6 | 3.7 | +| Debian Bookworm | ☐ | ☐ | 3.11 | 2.42 | 1.2020.2 | 0.9 | 2.1.8 | 3.6 | +| OpenSUSE 15.6 | ☐ | ☑ | 3.6 → 3.12 | 2.48 | 1.2020.9 | 0.8 | 2.1.6 | 3.5 | +| Ubuntu Noble | ☐ | ☐ | 3.12 | u2.42 | u1.2020.2 | u0.9 | 2.1.8 | u3.8 | +| Alma / Rocky 9 | ☑ | ☑ | 3.9 → 3.12 | 2.44 | e1.2024.6 | e0.8 | | | #### Previous -| os | https | up ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | gource | ffmpeg | -|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:|-----:|-------:| -| Alpine 3.19 | ☑ | ☐ | 3.11 | 9.0 | 1.2023.12 | 0.9 | 2.1.8 | 3.7 | 0.54 | 6.1.1 | -| Fedora 39 | ☑ | ☑ | 3.12 → 3.13 | 8.1 | 1.2024.6 | 0.9 | 2.1.6 | 3.5 | 0.55 | 6.1.1 | -| OpenSUSE 15.5 | ☐ | ☑ | 3.6 → 3.11 | 2.48 | 1.2020.9 | 0.8 | 2.1.6 | 3.5 | 0.54 | 4.4.4 | -| Alma / Rocky 8 | ☑ | ☑ | 3.6 → 3.12 | 2.40 | e1.2024.6 | e0.6 | | | | | +| os | https | updt-ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | +|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:| +| Alpine 3.19 | ☑ | ☐ | 3.11 | 9.0 | 1.2023.12 | 0.9 | 2.1.8 | 3.7 | +| Fedora 39 | ☑ | ☑ | 3.12 → 3.13 | 8.1 | 1.2024.6 | 0.9 | 2.1.6 | 3.5 | +| OpenSUSE 15.5 | ☐ | ☑ | 3.6 → 3.11 | 2.48 | 1.2020.9 | 0.8 | 2.1.6 | 3.5 | +| Alma / Rocky 8 | ☑ | ☑ | 3.6 → 3.12 | 2.40 | e1.2024.6 | e0.6 | | | #### Older Python -| os | https | up ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | gource | ffmpeg | -|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:|-----:|-------:| -| Ubuntu Jammy | ☐ | ☐ | 3.10 | u2.42 | u1.2020.2 | u0.8 | 2.1.6 | u3.4 | 0.51 | 4.4.2 | -| Debian Bullseye | ☐ | ☐ | 3.9 | 2.42 | 1.2020.2 | 0.7 | 2.1.6 | | 0.51 | 4.3.7 | +| os | https | updt-ca | python | graphviz | plantuml | shellcheck | shunit | shfmt | +|:----------------|---|---|------------:|------:|-----------:|------:|------:|-----:| +| Ubuntu Jammy | ☐ | ☐ | 3.10 | u2.42 | u1.2020.2 | u0.8 | 2.1.6 | u3.4 | +| Debian Bullseye | ☐ | ☐ | 3.9 | 2.42 | 1.2020.2 | 0.7 | 2.1.6 | | --- @@ -224,7 +224,6 @@ Handle project workflows in a unified way: #### Shell * comment -* git/pypi fallback for rwx/spcd * handle errors * packages * configure @@ -241,7 +240,6 @@ Handle project workflows in a unified way: * locales * persist * test -* workspace variable #### Shell → Python @@ -284,9 +282,7 @@ Handle project workflows in a unified way: ### Task stack * automate versions fetching -* gource, xvfb, xauth * handle openh264 repositories -* rpm fusion * tex * translate to french * try to support nix diff --git a/spcd.sh b/spcd.sh index 76cb937..a577aed 100755 --- a/spcd.sh +++ b/spcd.sh @@ -1,30 +1,27 @@ #! /usr/bin/env sh gource \ - --auto-skip-seconds 0.25 \ - --date-format "%Y / %m / %d ⋅ %H : %M : %S" \ - --disable-input \ - --font-scale 2.5 \ - --frameless \ - --hide mouse,usernames \ - --highlight-dirs \ - --key \ - --multi-sampling \ - --output-framerate 60 \ - --output-ppm-stream - \ - --seconds-per-day 0.6 \ - --stop-at-end \ - --viewport "1920x1080" | - ffmpeg \ - -codec:v ppm \ - -format image2pipe \ - -framerate 120 \ - -i - \ - -codec:v libx264 \ - -preset veryslow \ - -qp 28 \ - -movflags \ - +faststart \ - -pix_fmt yuv420p \ - -y \ - spcd.mp4 +--auto-skip-seconds 1 \ +--date-format "%Y / %m / %d ⋅ %H : %M : %S" \ +--disable-progress \ +-f \ +--hide mouse,usernames \ +--highlight-dirs \ +--key \ +--output-framerate 60 \ +--seconds-per-day 2.0 \ +--output-ppm-stream - \ +| \ +ffmpeg \ +-codec:v ppm \ +-format image2pipe \ +-framerate 120 \ +-i - \ +-codec:v libx264 \ +-preset veryslow \ +-qp 23 \ +-movflags \ ++faststart \ +-pix_fmt yuv420p \ +-y \ +spcd.mp4 diff --git a/spcd/bootstrap.sh b/spcd/bootstrap.sh index 747e02b..0268849 100644 --- a/spcd/bootstrap.sh +++ b/spcd/bootstrap.sh @@ -4,9 +4,9 @@ # │ __ = internal │ # ╰───────────────╯ -# __SPCD_BAR_TOP -# __SPCD_BAR_MIDDLE -# __SPCD_BAR_BOTTOM +# __SPCD_BANNER_TOP +# __SPCD_BANNER_MIDDLE +# __SPCD_BANNER_BOTTOM # __SPCD_STEP_LEVEL # __SPCD_STEP_level_INDEX @@ -36,35 +36,35 @@ _spcd_fill() { done } -# ╭───┬─────╮ -# │ _ │ bar │ -# ╰───┴─────╯ +# ╭───┬────────╮ +# │ _ │ banner │ +# ╰───┴────────╯ -_SPCD_BAR_BOTTOM_LEFT="${_SPCD_BOX_UP_AND_RIGHT}" -_SPCD_BAR_BOTTOM_MIDDLE="${_SPCD_BOX_UP_AND_HORIZONTAL}" -_SPCD_BAR_BOTTOM_RIGHT="${_SPCD_BOX_UP_AND_LEFT}" -_SPCD_BAR_HORIZONTAL="${_SPCD_BOX_HORIZONTAL}" -_SPCD_BAR_TOP_LEFT="${_SPCD_BOX_DOWN_AND_RIGHT}" -_SPCD_BAR_TOP_MIDDLE="${_SPCD_BOX_DOWN_AND_HORIZONTAL}" -_SPCD_BAR_TOP_RIGHT="${_SPCD_BOX_DOWN_AND_LEFT}" -_SPCD_BAR_VERTICAL="${_SPCD_BOX_VERTICAL}" +_SPCD_BANNER_BOTTOM_LEFT="${_SPCD_BOX_UP_AND_RIGHT}" +_SPCD_BANNER_BOTTOM_MIDDLE="${_SPCD_BOX_UP_AND_HORIZONTAL}" +_SPCD_BANNER_BOTTOM_RIGHT="${_SPCD_BOX_UP_AND_LEFT}" +_SPCD_BANNER_HORIZONTAL="${_SPCD_BOX_HORIZONTAL}" +_SPCD_BANNER_TOP_LEFT="${_SPCD_BOX_DOWN_AND_RIGHT}" +_SPCD_BANNER_TOP_MIDDLE="${_SPCD_BOX_DOWN_AND_HORIZONTAL}" +_SPCD_BANNER_TOP_RIGHT="${_SPCD_BOX_DOWN_AND_LEFT}" +_SPCD_BANNER_VERTICAL="${_SPCD_BOX_VERTICAL}" -_spcd_bar_add() { +_spcd_banner_add() { if [ -n "${1}" ]; then local text length filler text=" ${1} " length=${#text} - filler="$(_spcd_fill "${length}" "${_SPCD_BAR_HORIZONTAL}")" - if [ -n "${__SPCD_BAR_MIDDLE}" ]; then - _spcd_bar_split + filler="$(_spcd_fill "${length}" "${_SPCD_BANNER_HORIZONTAL}")" + if [ -n "${__SPCD_BANNER_MIDDLE}" ]; then + _spcd_banner_split else - _spcd_bar_open + _spcd_banner_open fi - _spcd_bar_append "${filler}" "${text}" "${filler}" + _spcd_banner_append "${filler}" "${text}" "${filler}" fi } -_spcd_bar_add_index() { +_spcd_banner_add_index() { local level value label while true; do level=$((level + 1)) @@ -76,68 +76,68 @@ _spcd_bar_add_index() { label="${value}" fi done - _spcd_bar_add "${label}" + _spcd_banner_add "${label}" } -_spcd_bar_append() { +_spcd_banner_append() { if [ -n "${3}" ]; then - __SPCD_BAR_TOP="${__SPCD_BAR_TOP}${1}" - __SPCD_BAR_MIDDLE="${__SPCD_BAR_MIDDLE}${2}" - __SPCD_BAR_BOTTOM="${__SPCD_BAR_BOTTOM}${3}" + __SPCD_BANNER_TOP="${__SPCD_BANNER_TOP}${1}" + __SPCD_BANNER_MIDDLE="${__SPCD_BANNER_MIDDLE}${2}" + __SPCD_BANNER_BOTTOM="${__SPCD_BANNER_BOTTOM}${3}" fi } -_spcd_bar_echo() { +_spcd_banner_echo() { echo "\ -${__SPCD_BAR_TOP} -${__SPCD_BAR_MIDDLE} -${__SPCD_BAR_BOTTOM}" +${__SPCD_BANNER_TOP} +${__SPCD_BANNER_MIDDLE} +${__SPCD_BANNER_BOTTOM}" } -_spcd_bar_open() { - _spcd_bar_append \ - "${_SPCD_BAR_TOP_LEFT}" \ - "${_SPCD_BAR_VERTICAL}" \ - "${_SPCD_BAR_BOTTOM_LEFT}" +_spcd_banner_open() { + _spcd_banner_append \ + "${_SPCD_BANNER_TOP_LEFT}" \ + "${_SPCD_BANNER_VERTICAL}" \ + "${_SPCD_BANNER_BOTTOM_LEFT}" } -_spcd_bar_render() { - _spcd_bar_wipe - _spcd_bar_add "S" - _spcd_bar_add_index +_spcd_banner_render() { + _spcd_banner_wipe + _spcd_banner_add "S" + _spcd_banner_add_index # local level value while true; do level=$((level + 1)) eval "value=\"\${__SPCD_STEP_${level}_LABEL}\"" [ -n "${value}" ] || break - _spcd_bar_add "${value}" + _spcd_banner_add "${value}" done # - _spcd_bar_shut - _spcd_bar_echo - _spcd_bar_wipe + _spcd_banner_shut + _spcd_banner_echo + _spcd_banner_wipe } -_spcd_bar_shut() { - _spcd_bar_append \ - "${_SPCD_BAR_TOP_RIGHT}" \ - "${_SPCD_BAR_VERTICAL}" \ - "${_SPCD_BAR_BOTTOM_RIGHT}" +_spcd_banner_shut() { + _spcd_banner_append \ + "${_SPCD_BANNER_TOP_RIGHT}" \ + "${_SPCD_BANNER_VERTICAL}" \ + "${_SPCD_BANNER_BOTTOM_RIGHT}" } -_spcd_bar_split() { - _spcd_bar_append \ - "${_SPCD_BAR_TOP_MIDDLE}" \ - "${_SPCD_BAR_VERTICAL}" \ - "${_SPCD_BAR_BOTTOM_MIDDLE}" +_spcd_banner_split() { + _spcd_banner_append \ + "${_SPCD_BANNER_TOP_MIDDLE}" \ + "${_SPCD_BANNER_VERTICAL}" \ + "${_SPCD_BANNER_BOTTOM_MIDDLE}" } -_spcd_bar_wipe() { +_spcd_banner_wipe() { unset \ - __SPCD_BAR_TOP \ - __SPCD_BAR_MIDDLE \ - __SPCD_BAR_BOTTOM + __SPCD_BANNER_TOP \ + __SPCD_BANNER_MIDDLE \ + __SPCD_BANNER_BOTTOM } # ╭───┬───────╮ @@ -199,7 +199,7 @@ _spcd_step_wipe() { _SPCD_TXT_CHARSET="UTF-8" _SPCD_TXT_LOCALE_DEFAULT="C" -_spcd_txt() { +_spcd_txt_pick() { case "${SPCD_TXT_LOCALE}" in "${SPCD_TXT_LOCALE_ENGLISH}") echo "${1}" ;; "${SPCD_TXT_LOCALE_FRENCH}") echo "${2}" ;; @@ -211,6 +211,54 @@ _spcd_txt() { # │ p = public │ # ╰────────────╯ +spcd_ca() { + local grep="\(After\|Before\|Issuer\|Signature Algorithm\|Subject:\)" + local index name value + local root="${2}" + while true; do + index=$((index + 1)) + name="SPCD_CA_${index}" + eval "value=\"\${${name}}\"" + [ -n "${value}" ] || break + case "${1}" in + "list") + echo "${name} =" + echo "${value}" | + openssl x509 -noout -text | + grep "${grep}" + ;; + "write") + spcd_os_write "${root}/${index}.crt" "${value}" + ;; + *) ;; + esac + done +} + +spcd_dns() { + local index name text value + while true; do + index=$((index + 1)) + name="SPCD_DNS_${index}" + eval "value=\"\${${name}}\"" + [ -n "${value}" ] || break + case "${1}" in + "list") + spcd_os_printenv "${name}" + ;; + "write") + text="${text}\ +nameserver ${value} +" + ;; + *) ;; + esac + done + if [ "${1}" = "write" ]; then + spcd_os_write "/etc/resolv.conf" "${text}" + fi +} + spcd_run() { if [ -n "${1}" ]; then _spcd_frame_open "${@}" @@ -320,7 +368,7 @@ spcd_step() { local index="${prefix}_INDEX" eval "${index}=\$((${index} + 1))" eval "${prefix}_LABEL=\"${1}\"" - _spcd_bar_render + _spcd_banner_render fi } @@ -342,19 +390,19 @@ spcd_step_out() { SPCD_TXT_LOCALE_ENGLISH="en_US" SPCD_TXT_LOCALE_FRENCH="fr_FR" -spcd_txt() { +spcd_txt_get() { case "${1}" in - "set") _spcd_txt "Set" "Définir" ;; + "set") _spcd_txt_pick "Set" "Définir" ;; *) ;; esac } -# ╭─────────────────╮ -# │ e = environment │ -# ╰─────────────────╯ +# ╭──────────╮ +# │ s = step │ +# ╰──────────╯ # ╭───┬───────────╮ -# │ e │ constants │ +# │ s │ constants │ # ╰───┴───────────╯ SPCD_OS_ALMA="alma" @@ -372,12 +420,43 @@ SPCD_PM_DNF="dnf" SPCD_PM_PACMAN="pacman" SPCD_PM_ZYPPER="zypper" -# ╭───┬───────────╮ -# │ e │ functions │ -# ╰───┴───────────╯ +# ╭───┬─────────────╮ +# │ s │ environment │ +# ╰───┴─────────────╯ -spcd_e_default() { - spcd_step "$(spcd_txt "set")" +spcd_step__environment_print() { + spcd_ca "list" + spcd_dns "list" + set -- \ + "GIT_RWX" \ + "GIT_SPCD" \ + "GIT_SHUNIT" \ + "REF_FEATURE" \ + "REF_RELEASE" \ + "REF_STAGING" \ + "TXT_LOCALE" \ + "URL_ALMA" \ + "URL_ALPINE" \ + "URL_ARCH" \ + "URL_DEBIAN" \ + "URL_EPEL" \ + "URL_FEDORA" \ + "URL_OPENSUSE" \ + "URL_PYTHON" \ + "URL_ROCKY" \ + "URL_UBUNTU" + local item name value + for item in "${@}"; do + name="SPCD_${item}" + eval "value=\"\${${name}}\"" + if [ -n "${value}" ]; then + spcd_os_printenv "${name}" + fi + done +} + +spcd_step__environment_defaults_set() { + spcd_step "$(spcd_txt_get "set")" [ -n "${SPCD_DNS_1}" ] || SPCD_DNS_1="9.9.9.9" @@ -405,7 +484,6 @@ spcd_e_default() { # /$repo/os/$arch SPCD_URL_ARCH="https://geo.mirror.pkgbuild.com" [ -n "${SPCD_URL_DEBIAN}" ] || - # /dists/… SPCD_URL_DEBIAN="https://deb.debian.org/debian" [ -n "${SPCD_URL_EPEL}" ] || # /$releasever/Everything/… @@ -429,11 +507,10 @@ spcd_e_default() { # /$contentdir/$releasever/… SPCD_URL_ROCKY="https://dl.rockylinux.org" [ -n "${SPCD_URL_UBUNTU}" ] || - # /dists/… SPCD_URL_UBUNTU="https://ubuntu.mirrors.ovh.net/ubuntu" } -spcd_e_set() { +spcd_step__environment_set_variables() { spcd_step "Set variables" # check script first [ -n "${SPCD}" ] || spcd_error_ci "SPCD" @@ -708,268 +785,27 @@ ${SPCD_PYTHON_VENV}/lib/${SPCD_PYTHON_COMMAND}/site-packages" spcd_os_printenv "SPCD_DL" } +spcd_step__environment_list_workspace() { + spcd_step "List workspace" + spcd_os_ls "$(realpath .)" +} + # ╭──────────────╮ # │ f = function │ # ╰──────────────╯ -spcd_f_dns() { - local index name text value - while true; do - index=$((index + 1)) - name="SPCD_DNS_${index}" - eval "value=\"\${${name}}\"" - [ -n "${value}" ] || break - case "${1}" in - "list") - spcd_os_printenv "${name}" - ;; - "write") - text="${text}\ -nameserver ${value} -" - ;; - *) ;; - esac - done - if [ "${1}" = "write" ]; then - spcd_os_write "/etc/resolv.conf" "${text}" - fi -} - -spcd_f_pkg() { - spcd_step_in "OS packages" - local file - # epel - spcd_step "EPEL" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") - spcd_f_pm_pkg_install "epel-release" - case "${SPCD_OS_VERSION}" in - "9") - set -- \ - "-testing" \ - "" - ;; - "8") - set -- \ - "-modular" \ - "-testing-modular" \ - "-testing" \ - "" - ;; - *) ;; - esac - for file in "${@}"; do - spcd_os_sed "/etc/yum.repos.d/epel${file}.repo" \ - "|^metalink|#metalink|" \ - "|https://download.example/pub/epel|${SPCD_URL_EPEL}|" \ - "|^#baseurl|baseurl|" - done - file="/etc/yum.repos.d/epel-cisco-openh264.repo" - if [ -f "${file}" ]; then - spcd_os_sed "${file}" \ - "|^enabled=1|enabled=0|" - fi - spcd_f_pm_pkg_update - ;; - *) ;; - esac - # ffmpeg - spcd_step "FFMPEG" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") - case "${SPCD_OS_VERSION}" in - "8") ;; - *) - dnf config-manager --enable "crb" - spcd_f_pm_pkg_install "ffmpeg-free" - ;; - esac - ;; - "${SPCD_OS_FEDORA}") spcd_f_pm_pkg_install "ffmpeg-free" ;; - "${SPCD_OS_OPENSUSE}") spcd_f_pm_pkg_install "ffmpeg-4" ;; - *) spcd_f_pm_pkg_install "ffmpeg" ;; - esac - # gource - spcd_step "Gource" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") ;; - *) spcd_f_pm_pkg_install "gource" ;; - esac - # graphviz - spcd_step "GraphViz" - spcd_f_pm_pkg_install "graphviz" - # openssh - spcd_step "OpenSSH" - case "${SPCD_PM}" in - "${SPCD_PM_APK}" | "${SPCD_PM_APT}") - spcd_f_pm_pkg_install "openssh-client" - ;; - "${SPCD_PM_DNF}" | "${SPCD_PM_ZYPPER}") - spcd_f_pm_pkg_install "openssh-clients" - ;; - "${SPCD_PM_PACMAN}") spcd_f_pm_pkg_install "openssh" ;; - *) ;; - esac - # plantuml - spcd_step "PlantUML" - spcd_f_pm_pkg_install "plantuml" - # rsync - spcd_step "Rsync" - spcd_f_pm_pkg_install "rsync" - # shell check - spcd_step "ShellCheck" - case "${SPCD_PM}" in - "${SPCD_PM_DNF}" | "${SPCD_PM_ZYPPER}") - spcd_f_pm_pkg_install "ShellCheck" - ;; - *) spcd_f_pm_pkg_install "shellcheck" ;; - esac - # shfmt - spcd_step "ShellFormat" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") ;; - "${SPCD_OS_DEBIAN}") - case "${SPCD_OS_VERSION}" in - "bullseye") ;; - *) spcd_f_pm_pkg_install "shfmt" ;; - esac - ;; - *) spcd_f_pm_pkg_install "shfmt" ;; - esac - spcd_step_out -} - -# ╭───┬──────────────────────────────╮ -# │ f │ ca = certificate authorities │ -# ╰───┴──────────────────────────────╯ - -spcd_f_ca() { - case "${1}" in - "list") - local grep="\(After\|Before\|Issuer\|Signature Algorithm\|Subject:\)" - ;; - "write") - local root - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALMA}" | "${SPCD_OS_FEDORA}" | "${SPCD_OS_ROCKY}") - root="/etc/pki/ca-trust/source/anchors" - ;; - "${SPCD_OS_ALPINE}" | "${SPCD_OS_DEBIAN}" | "${SPCD_OS_UBUNTU}") - root="/usr/local/share/ca-certificates" - ;; - "${SPCD_OS_ARCH}") - root="/etc/ca-certificates/trust-source/anchors" - ;; - "${SPCD_OS_OPENSUSE}") - root="/etc/pki/trust/anchors" - ;; - *) ;; - esac - spcd_os_mkdir "${root}" - ;; - *) ;; - esac - local index name value - while true; do - index=$((index + 1)) - name="SPCD_CA_${index}" - eval "value=\"\${${name}}\"" - [ -n "${value}" ] || break - case "${1}" in - "list") - echo "${name} =" - echo "${value}" | - openssl x509 -noout -text | - grep "${grep}" - ;; - "write") - spcd_os_write "${root}/${index}.crt" "${value}" - ;; - *) ;; - esac - done -} - -spcd_f_ca_install() { - spcd_step "Install package" - spcd_f_pm_pkg_install "ca-certificates" -} - -spcd_f_ca_update() { - spcd_step "Update certificates" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ARCH}" | \ - "${SPCD_OS_ALMA}" | \ - "${SPCD_OS_FEDORA}" | \ - "${SPCD_OS_ROCKY}") - spcd_run update-ca-trust - ;; - "${SPCD_OS_ALPINE}" | \ - "${SPCD_OS_DEBIAN}" | \ - "${SPCD_OS_OPENSUSE}" | \ - "${SPCD_OS_UBUNTU}") - spcd_run update-ca-certificates - ;; - *) ;; - esac -} - -# ╭───┬───────────────────╮ -# │ f │ env = environment │ -# ╰───┴───────────────────╯ - -spcd_f_env_list() { - spcd_f_ca "list" - spcd_f_dns "list" - set -- \ - "GIT_RWX" \ - "GIT_SPCD" \ - "GIT_SHUNIT" \ - "REF_FEATURE" \ - "REF_RELEASE" \ - "REF_STAGING" \ - "TXT_LOCALE" \ - "URL_ALMA" \ - "URL_ALPINE" \ - "URL_ARCH" \ - "URL_DEBIAN" \ - "URL_EPEL" \ - "URL_FEDORA" \ - "URL_OPENSUSE" \ - "URL_PYTHON" \ - "URL_ROCKY" \ - "URL_UBUNTU" - local item name value - for item in "${@}"; do - name="SPCD_${item}" - eval "value=\"\${${name}}\"" - if [ -n "${value}" ]; then - spcd_os_printenv "${name}" - fi - done -} - -spcd_f_env_workspace() { - spcd_os_ls "$(realpath .)" -} - -# ╭───┬─────╮ -# │ f │ git │ -# ╰───┴─────╯ - -spcd_f_git_clone() { +spcd_git_clone() { if [ -n "${1}" ]; then local name path url name="$(basename "${1}")" path="${SPCD_DL}/${name}" - url="$(spcd_f_git_url "${1}")" + url="$(spcd_git_url "${1}")" git clone "${url}" "${path}" echo "${path}" fi } -spcd_f_git_url() { +spcd_git_url() { if [ -n "${1}" ]; then case "${1}" in http*) echo "${1}" ;; @@ -979,68 +815,309 @@ spcd_f_git_url() { fi } -# ╭───┬───────────────╮ -# │ f │ pkg = package │ -# ╰───┴───────────────╯ - -spcd_f_pkg_dos2unix() { - spcd_step "Install dos2unix" - spcd_f_pm_pkg_install "dos2unix" +spcd_python_ln() { + local command="${1}" + if [ -n "${command}" ]; then + echo "→ ${SPCD_PYTHON_ALIAS} → ${command}" + ln -f -s "${command}" \ + "/usr/bin/${SPCD_PYTHON_ALIAS}" + fi } -spcd_f_pkg_git() { - spcd_step "Install Git" - spcd_f_pm_pkg_install "git" +spcd_python_pip() { + if [ -n "${1}" ]; then + local name path target + name="$(basename "${1}")" + path="$(spcd_git_clone "${1}")" + path="${path}/${name}" + target="${SPCD_PYTHON_VENV_PACKAGES}" + cp --recursive "${path}" "${target}" + echo "${target}/${name}" + fi } -# ╭───┬──────────────────────╮ -# │ f │ pm = package manager │ -# ╰───┴──────────────────────╯ +spcd_txt_locale() { + local action="${1}" + local chosen="${2}" + set -- \ + "LANG" \ + "LC_CTYPE" \ + "LC_NUMERIC" \ + "LC_TIME" \ + "LC_COLLATE" \ + "LC_MONETARY" \ + "LC_MESSAGES" + case "${SPCD_OS_ID}" in + "${SPCD_OS_ALPINE}") ;; + *) + set -- \ + "${@}" \ + "LANGUAGE" \ + "LC_PAPER" \ + "LC_NAME" \ + "LC_ADDRESS" \ + "LC_TELEPHONE" \ + "LC_MEASUREMENT" \ + "LC_IDENTIFICATION" + ;; + esac + local name + case "${action}" in + "list") + if ! locale; then + for name in "${@}"; do + spcd_os_printenv "${name}" + done + fi + ;; + "set") + spcd_txt_locale "list" + spcd_split + local locale long + if [ -n "${chosen}" ]; then + locale="${chosen}" + else + locale="${_SPCD_TXT_LOCALE_DEFAULT}" + fi + long="${locale}.${_SPCD_TXT_CHARSET}" + for name in "${@}"; do + if [ "${name}" != "LANGUAGE" ]; then + export "${name}=${long}" + else + export "${name}=$(spcd_txt_locales language "${chosen}")" + fi + done + spcd_split + spcd_txt_locale "list" + ;; + "show") + local regex + for name in "${@}"; do + unset regex + case "${name}" in + # LC_CTYPE + "LC_NUMERIC") regex="^\(decimal\|thousands\|grouping\)" ;; + "LC_TIME") regex="^\(day\|mon\)" ;; + # LC_COLLATE + "LC_MONETARY") + case "${SPCD_OS_ID}" in + "${SPCD_OS_ALPINE}") ;; + *) regex="^\(int_curr\|currency\|mon_\)" ;; + esac + ;; + "LC_MESSAGES") regex="^\(yes\|no\)" ;; + "LC_PAPER") regex="^\(height\|width\)" ;; + "LC_NAME") regex="^name_m" ;; + "LC_ADDRESS") regex="^\(country\|lang\)_name" ;; + "LC_TELEPHONE") regex="^int_" ;; + "LC_MEASUREMENT") regex="^measurement=" ;; + "LC_IDENTIFICATION") regex="^\(language\|territory\|title\)" ;; + *) ;; + esac + spcd_split + spcd_os_printenv "${name}" + if [ -n "${regex}" ]; then + locale --keyword-name "${name}" | grep "${regex}" + fi + done + ;; + *) ;; + esac +} -# ╭───┬────┬──────────────────╮ -# │ f │ pm │ conf = configure │ -# ╰───┴────┴──────────────────╯ +spcd_txt_locales() { + local action="${1}" + local chosen="${2}" + set -- \ + "${SPCD_TXT_LOCALE_ENGLISH}" \ + "${SPCD_TXT_LOCALE_FRENCH}" + local name + case "${action}" in + "install") + spcd_txt_locales "list" + spcd_split + case "${SPCD_PM}" in + "${SPCD_PM_APK}") + spcd_f_pm_install "musl-locales" + export MUSL_LOCPATH="/usr/share/i18n/locales/musl" + ;; + "${SPCD_PM_APT}") + local text + for name in "${@}"; do + text="${text}\ +${name}.${_SPCD_TXT_CHARSET} ${_SPCD_TXT_CHARSET} +" + done + spcd_os_write "/etc/locale.gen" "${text}" + spcd_f_pm_install "locales" + ;; + "${SPCD_PM_DNF}") + local language + for name in "${@}"; do + language="$(echo "${name}" | cut -d _ -f 1)" + spcd_f_pm_install "glibc-langpack-${language}" + done + ;; + "${SPCD_PM_PACMAN}") spcd_f_pm_install "glibc-locales" ;; + "${SPCD_PM_ZYPPER}") spcd_f_pm_install "glibc-locale" ;; + *) ;; + esac + spcd_split + spcd_txt_locales "list" + ;; + "language") + local text + if [ -n "${chosen}" ]; then + text="${chosen}" + fi + for name in "${@}"; do + if [ "${name}" != "${chosen}" ]; then + if [ -n "${text}" ]; then + text="${text}:${name}" + else + text="${name}" + fi + fi + done + ;; + "list") + if ! spcd_run locale --all-locales; then + echo "No locales yet!" + fi + ;; + *) ;; + esac +} -spcd_f_pm_conf() { - spcd_step "Set configuration" +# ╭───┬────╮ +# │ f │ pm │ +# ╰───┴────╯ + +spcd_f_pm_clean() { case "${SPCD_PM}" in - "${SPCD_PM_DNF}") - spcd_os_write "/etc/dnf/dnf.conf" "\ -[main] -best=True -clean_requirements_on_remove=True -gpgcheck=1 -installonly_limit=3 -skip_if_unavailable=False -" - ;; - "${SPCD_PM_APK}") ;; - "${SPCD_PM_PACMAN}") ;; - "${SPCD_PM_APT}") - spcd_os_write "/etc/apt/apt.conf.d/apt.conf" "\ -Acquire::Check-Valid-Until True; -APT::Get::Show-Versions True; -APT::Install-Recommends False; -APT::Install-Suggests False; -Dir::Etc::SourceParts \"\"; -" - ;; + "${SPCD_PM_APK}") spcd_run apk cache purge ;; + "${SPCD_PM_APT}") spcd_run apt-get clean ;; + "${SPCD_PM_DNF}") spcd_run dnf clean all ;; + "${SPCD_PM_PACMAN}") spcd_run pacman --sync --clean --noconfirm ;; + "${SPCD_PM_ZYPPER}") spcd_run zypper clean ;; + *) ;; + esac +} + +spcd_f_pm_install() { + case "${SPCD_PM}" in + "${SPCD_PM_APK}") spcd_run apk add "${1}" ;; + "${SPCD_PM_APT}") spcd_run apt-get install --assume-yes "${1}" ;; + "${SPCD_PM_DNF}") spcd_run dnf install --assumeyes "${1}" ;; + "${SPCD_PM_PACMAN}") spcd_run pacman --sync --noconfirm "${1}" ;; + "${SPCD_PM_ZYPPER}") spcd_run zypper --non-interactive install "${1}" ;; + *) ;; + esac + spcd_f_pm_clean +} + +spcd_f_pm_query() { + case "${SPCD_PM}" in + "${SPCD_PM_APK}") apk info "${1}" ;; + "${SPCD_PM_APT}") dpkg-query --show "${1}" ;; + "${SPCD_PM_DNF}") rpm --query "${1}" ;; + "${SPCD_PM_PACMAN}") pacman --query "${1}" ;; + "${SPCD_PM_ZYPPER}") rpm --query "${1}" ;; + *) ;; + esac +} + +spcd_f_pm_update() { + spcd_step "Update" + case "${SPCD_PM}" in + "${SPCD_PM_APK}") spcd_run apk update ;; + "${SPCD_PM_APT}") spcd_run apt-get update ;; + "${SPCD_PM_DNF}") spcd_run dnf makecache ;; + "${SPCD_PM_PACMAN}") spcd_run pacman --sync --refresh ;; + "${SPCD_PM_ZYPPER}") spcd_run zypper refresh ;; + *) ;; + esac +} + +spcd_f_pm_upgrade() { + spcd_step "Upgrade" + case "${SPCD_PM}" in + "${SPCD_PM_APK}") spcd_run apk upgrade ;; + "${SPCD_PM_APT}") spcd_run apt-get upgrade --assume-yes ;; + "${SPCD_PM_DNF}") spcd_run dnf upgrade --assumeyes ;; + "${SPCD_PM_PACMAN}") spcd_run pacman --sync --sysupgrade --noconfirm ;; + "${SPCD_PM_ZYPPER}") spcd_run zypper --non-interactive update ;; + *) ;; + esac +} + +# ╭───┬────┬───────╮ +# │ f │ pm │ https │ +# ╰───┴────┴───────╯ + +spcd_f_pm_https_path() { + case "${SPCD_PM}" in + "${SPCD_PM_APK}") echo "/etc/apk/repositories.d/https" ;; + "${SPCD_PM_APT}") echo "/etc/apt/apt.conf.d/https" ;; + "${SPCD_PM_DNF}") echo "/etc/dnf/dnf.conf.d/https.conf" ;; + "${SPCD_PM_PACMAN}") echo "/etc/pacman.d/https.conf" ;; "${SPCD_PM_ZYPPER}") ;; *) ;; esac - case "${SPCD_OS_ID}" in - "${SPCD_OS_ARCH}") - spcd_run pacman-key --init - ;; - "${SPCD_OS_DEBIAN}" | "${SPCD_OS_UBUNTU}") - export DEBIAN_FRONTEND="noninteractive" - spcd_os_printenv DEBIAN_FRONTEND - ;; - *) ;; - esac } -spcd_f_pm_conf_repos() { +spcd_f_pm_https_trust() { + spcd_step "Trust" + local path text + if [ -n "${SPCD_CA_1}" ] || [ "${SPCD_PM}" = "${SPCD_PM_APT}" ]; then + path="$(spcd_f_pm_https_path)" + if [ -n "${path}" ]; then + spcd_os_mkdir "$(dirname "${path}")" + case "${SPCD_PM}" in + "${SPCD_PM_APK}") text="\ +--no-verify +" ;; + "${SPCD_PM_APT}") text="\ +Acquire::https::Verify-Peer False; +" ;; + "${SPCD_PM_DNF}") text="\ +sslverify=False +" ;; + "${SPCD_PM_PACMAN}") text="\ +SSLVerify = No +" ;; + "${SPCD_PM_ZYPPER}") ;; + *) ;; + esac + [ -n "${text}" ] && + spcd_os_write "${path}" "${text}" + fi + fi +} + +spcd_f_pm_https_verify() { + spcd_step "Verify" + local path + path="$(spcd_f_pm_https_path)" + if [ -n "${path}" ]; then + spcd_os_rm "${path}" + fi +} + +# ╭───┬─────╮ +# │ s │ dns │ +# ╰───┴─────╯ + +spcd_step__dns() { + spcd_step "DNS" + spcd_dns "write" +} + +# ╭───┬──────────╮ +# │ s │ packages │ +# ╰───┴──────────╯ + +spcd_step__packages_set_repositories() { spcd_step "Set repositories" local file case "${SPCD_OS_ID}" in @@ -1182,187 +1259,143 @@ deb ${SPCD_URL_UBUNTU} ${SPCD_OS_VERSION}-security main universe esac } -# ╭───┬────┬───────╮ -# │ f │ pm │ https │ -# ╰───┴────┴───────╯ - -spcd_f_pm_https_path() { +spcd_step__packages_set_configuration() { + spcd_step "Set configuration" case "${SPCD_PM}" in - "${SPCD_PM_APK}") echo "/etc/apk/repositories.d/https" ;; - "${SPCD_PM_APT}") echo "/etc/apt/apt.conf.d/https" ;; - "${SPCD_PM_DNF}") echo "/etc/dnf/dnf.conf.d/https.conf" ;; - "${SPCD_PM_PACMAN}") echo "/etc/pacman.d/https.conf" ;; + "${SPCD_PM_DNF}") + spcd_os_write "/etc/dnf/dnf.conf" "\ +[main] +best=True +clean_requirements_on_remove=True +gpgcheck=1 +installonly_limit=3 +skip_if_unavailable=False +" + ;; + "${SPCD_PM_APK}") ;; + "${SPCD_PM_PACMAN}") ;; + "${SPCD_PM_APT}") + spcd_os_write "/etc/apt/apt.conf.d/apt.conf" "\ +Acquire::Check-Valid-Until True; +APT::Get::Show-Versions True; +APT::Install-Recommends False; +APT::Install-Suggests False; +Dir::Etc::SourceParts \"\"; +" + ;; "${SPCD_PM_ZYPPER}") ;; *) ;; esac -} - -spcd_f_pm_https_trust() { - spcd_step "Trust" - local path text - if [ -n "${SPCD_CA_1}" ] || [ "${SPCD_PM}" = "${SPCD_PM_APT}" ]; then - path="$(spcd_f_pm_https_path)" - if [ -n "${path}" ]; then - spcd_os_mkdir "$(dirname "${path}")" - case "${SPCD_PM}" in - "${SPCD_PM_APK}") text="\ ---no-verify -" ;; - "${SPCD_PM_APT}") text="\ -Acquire::https::Verify-Peer False; -" ;; - "${SPCD_PM_DNF}") text="\ -sslverify=False -" ;; - "${SPCD_PM_PACMAN}") text="\ -SSLVerify = No -" ;; - "${SPCD_PM_ZYPPER}") ;; - *) ;; - esac - [ -n "${text}" ] && - spcd_os_write "${path}" "${text}" - fi - fi -} - -spcd_f_pm_https_verify() { - spcd_step "Verify" - local path - path="$(spcd_f_pm_https_path)" - if [ -n "${path}" ]; then - spcd_os_rm "${path}" - fi -} - -# ╭───┬────┬─────╮ -# │ f │ pm │ pkg │ -# ╰───┴────┴─────╯ - -spcd_f_pm_pkg_clean() { - case "${SPCD_PM}" in - "${SPCD_PM_APK}") spcd_run apk cache purge ;; - "${SPCD_PM_APT}") spcd_run apt-get clean ;; - "${SPCD_PM_DNF}") spcd_run dnf clean all ;; - "${SPCD_PM_PACMAN}") spcd_run pacman --sync --clean --noconfirm ;; - "${SPCD_PM_ZYPPER}") spcd_run zypper clean ;; + case "${SPCD_OS_ID}" in + "${SPCD_OS_ARCH}") + spcd_run pacman-key --init + ;; + "${SPCD_OS_DEBIAN}" | "${SPCD_OS_UBUNTU}") + export DEBIAN_FRONTEND="noninteractive" + spcd_os_printenv DEBIAN_FRONTEND + ;; *) ;; esac } -spcd_f_pm_pkg_install() { - if [ -n "${1}" ]; then - local name - for name in "${@}"; do - case "${SPCD_PM}" in - "${SPCD_PM_APK}") spcd_run apk add "${1}" ;; - "${SPCD_PM_APT}") spcd_run apt-get install --assume-yes "${1}" ;; - "${SPCD_PM_DNF}") spcd_run dnf install --assumeyes "${1}" ;; - "${SPCD_PM_PACMAN}") spcd_run pacman --sync --noconfirm "${1}" ;; - "${SPCD_PM_ZYPPER}") - spcd_run zypper --non-interactive install "${1}" - ;; - *) ;; - esac - spcd_f_pm_pkg_clean - done - else - case "${SPCD_PM}" in - "${SPCD_PM_APT}") spcd_f_pm_pkg_install "apt-utils" ;; - "${SPCD_PM_DNF}") spcd_f_pm_pkg_install "dnf-plugins-core" ;; - *) ;; - esac - fi -} - -spcd_f_pm_pkg_query() { +spcd_step__packages_install_tools() { + spcd_step "Install tools" case "${SPCD_PM}" in - "${SPCD_PM_APK}") apk info "${1}" ;; - "${SPCD_PM_APT}") dpkg-query --show "${1}" ;; - "${SPCD_PM_DNF}") rpm --query "${1}" ;; - "${SPCD_PM_PACMAN}") pacman --query "${1}" ;; - "${SPCD_PM_ZYPPER}") rpm --query "${1}" ;; + "${SPCD_PM_APT}") spcd_f_pm_install "apt-utils" ;; *) ;; esac } -spcd_f_pm_pkg_update() { - spcd_step "Update" - case "${SPCD_PM}" in - "${SPCD_PM_APK}") spcd_run apk update ;; - "${SPCD_PM_APT}") spcd_run apt-get update ;; - "${SPCD_PM_DNF}") spcd_run dnf makecache ;; - "${SPCD_PM_PACMAN}") spcd_run pacman --sync --refresh ;; - "${SPCD_PM_ZYPPER}") spcd_run zypper refresh ;; - *) ;; - esac -} - -spcd_f_pm_pkg_upgrade() { - spcd_step "Upgrade" - case "${SPCD_PM}" in - "${SPCD_PM_APK}") spcd_run apk upgrade ;; - "${SPCD_PM_APT}") spcd_run apt-get upgrade --assume-yes ;; - "${SPCD_PM_DNF}") spcd_run dnf upgrade --assumeyes ;; - "${SPCD_PM_PACMAN}") spcd_run pacman --sync --sysupgrade --noconfirm ;; - "${SPCD_PM_ZYPPER}") spcd_run zypper --non-interactive update ;; - *) ;; - esac -} - -# ╭───┬─────────────╮ -# │ f │ py = python │ -# ╰───┴─────────────╯ - -spcd_f_py_clone() { - if [ -n "${1}" ]; then - local name path target - name="$(basename "${1}")" - path="$(spcd_f_git_clone "${1}")" - path="${path}/${name}" - target="${SPCD_PYTHON_VENV_PACKAGES}" - cp --recursive "${path}" "${target}" - echo "${target}/${name}" - fi -} - -spcd_f_py_download() { - spcd_step_in "Modules" - local target path script check - target="${SPCD_PYTHON_VENV_PACKAGES}" - spcd_step "List" - spcd_os_ls "${target}" - spcd_step "Main" - path="$(spcd_f_py_clone "${SPCD_GIT_SPCD}")" - # check matching of file and variable - spcd_step "Check" - script="${path}/bootstrap.sh" - ls -l "${script}" - check="${script}.${_SPCD_CMD_SUM}" - "${_SPCD_CMD_SUM}" "${script}" >"${check}" - printf "%s" "${SPCD}" >"${script}" - ls -l "${script}" - dos2unix "${script}" - ls -l "${script}" - "${_SPCD_CMD_SUM}" -c "${check}" || spcd_error_ci "SPCD" - spcd_step "Root" - spcd_f_py_clone "${SPCD_GIT_RWX}" - spcd_step "List" - spcd_os_ls "${target}" +spcd_step__packages_install_locales() { + spcd_step_in "Locales" + spcd_step "Install" + spcd_txt_locales "install" + spcd_step "Set" + spcd_txt_locale "set" "${SPCD_TXT_LOCALE}" + spcd_step "Show" + spcd_txt_locale "show" spcd_step_out } -spcd_f_py_install() { +# ╭───┬────╮ +# │ s │ ca │ +# ╰───┴────╯ + +spcd_step__ca_install_package() { spcd_step "Install package" - spcd_f_pm_pkg_install "${SPCD_PYTHON_PACKAGE}" + spcd_f_pm_install "ca-certificates" +} + +spcd_step__ca_write_certificates() { + spcd_step "Write certificates" + local root + case "${SPCD_OS_ID}" in + "${SPCD_OS_ALMA}" | "${SPCD_OS_FEDORA}" | "${SPCD_OS_ROCKY}") + root="/etc/pki/ca-trust/source/anchors" + ;; + "${SPCD_OS_ALPINE}" | "${SPCD_OS_DEBIAN}" | "${SPCD_OS_UBUNTU}") + root="/usr/local/share/ca-certificates" + ;; + "${SPCD_OS_ARCH}") + root="/etc/ca-certificates/trust-source/anchors" + ;; + "${SPCD_OS_OPENSUSE}") + root="/etc/pki/trust/anchors" + ;; + *) ;; + esac + spcd_os_mkdir "${root}" + spcd_ca "write" "${root}" +} + +spcd_step__ca_update_certificates() { + spcd_step "Update certificates" + case "${SPCD_OS_ID}" in + "${SPCD_OS_ARCH}" | \ + "${SPCD_OS_ALMA}" | \ + "${SPCD_OS_FEDORA}" | \ + "${SPCD_OS_ROCKY}") + spcd_run update-ca-trust + ;; + "${SPCD_OS_ALPINE}" | \ + "${SPCD_OS_DEBIAN}" | \ + "${SPCD_OS_OPENSUSE}" | \ + "${SPCD_OS_UBUNTU}") + spcd_run update-ca-certificates + ;; + *) ;; + esac +} + +# ╭───┬──────────╮ +# │ s │ packages │ +# ╰───┴──────────╯ + +spcd_step__packages_install_dos2unix() { + spcd_step "Install dos2unix" + spcd_f_pm_install "dos2unix" +} + +spcd_step__packages_install_git() { + spcd_step "Install Git" + spcd_f_pm_install "git" +} + +# ╭───┬────────╮ +# │ s │ python │ +# ╰───┴────────╯ + +spcd_step__python_install() { + spcd_step "Install package" + spcd_f_pm_install "${SPCD_PYTHON_PACKAGE}" spcd_step "Link alias to command" - spcd_f_py_link "${SPCD_PYTHON_COMMAND}" + spcd_python_ln "${SPCD_PYTHON_COMMAND}" # venv spcd_step_in "Virtual environment" spcd_step "Install package" case "${SPCD_OS_ID}" in "${SPCD_OS_DEBIAN}" | "${SPCD_OS_UBUNTU}") - spcd_f_pm_pkg_install "python3-venv" + spcd_f_pm_install "python3-venv" ;; *) ;; esac @@ -1379,17 +1412,115 @@ index-url = ${SPCD_URL_PYTHON}/simple spcd_step_out } -spcd_f_py_link() { - local command="${1}" - if [ -n "${command}" ]; then - echo "→ ${SPCD_PYTHON_ALIAS} → ${command}" - ln -f -s "${command}" \ - "/usr/bin/${SPCD_PYTHON_ALIAS}" - fi +spcd_step__python_modules() { + spcd_step_in "Modules" + local target path script check + target="${SPCD_PYTHON_VENV_PACKAGES}" + spcd_step "List" + spcd_os_ls "${target}" + spcd_step "Main" + path="$(spcd_python_pip "${SPCD_GIT_SPCD}")" + # check matching of file and variable + spcd_step "Check" + script="${path}/bootstrap.sh" + ls -l "${script}" + check="${script}.${_SPCD_CMD_SUM}" + "${_SPCD_CMD_SUM}" "${script}" >"${check}" + printf "%s" "${SPCD}" >"${script}" + ls -l "${script}" + dos2unix "${script}" + ls -l "${script}" + "${_SPCD_CMD_SUM}" -c "${check}" || spcd_error_ci "SPCD" + spcd_step "Root" + spcd_python_pip "${SPCD_GIT_RWX}" + spcd_step "List" + spcd_os_ls "${target}" + spcd_step_out } -spcd_f_py_save() { - spcd_step "Save" +spcd_step__install_packages() { + spcd_step_in "OS packages" + local file + # epel + spcd_step "EPEL" + case "${SPCD_OS_ID}" in + "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") + spcd_f_pm_install "epel-release" + case "${SPCD_OS_VERSION}" in + "9") + set -- \ + "-testing" \ + "" + ;; + "8") + set -- \ + "-modular" \ + "-testing-modular" \ + "-testing" \ + "" + ;; + *) ;; + esac + for file in "${@}"; do + spcd_os_sed "/etc/yum.repos.d/epel${file}.repo" \ + "|^metalink|#metalink|" \ + "|https://download.example/pub/epel|${SPCD_URL_EPEL}|" \ + "|^#baseurl|baseurl|" + done + file="/etc/yum.repos.d/epel-cisco-openh264.repo" + if [ -f "${file}" ]; then + spcd_os_sed "${file}" \ + "|^enabled=1|enabled=0|" + fi + ;; + *) ;; + esac + # graphviz + spcd_step "GraphViz" + spcd_f_pm_install "graphviz" + # openssh + spcd_step "OpenSSH" + case "${SPCD_PM}" in + "${SPCD_PM_APK}" | "${SPCD_PM_APT}") + spcd_f_pm_install "openssh-client" + ;; + "${SPCD_PM_DNF}" | "${SPCD_PM_ZYPPER}") + spcd_f_pm_install "openssh-clients" + ;; + "${SPCD_PM_PACMAN}") spcd_f_pm_install "openssh" ;; + *) ;; + esac + # plantuml + spcd_step "PlantUML" + spcd_f_pm_install "plantuml" + # rsync + spcd_step "Rsync" + spcd_f_pm_install "rsync" + # shell check + spcd_step "ShellCheck" + case "${SPCD_PM}" in + "${SPCD_PM_DNF}" | "${SPCD_PM_ZYPPER}") + spcd_f_pm_install "ShellCheck" + ;; + *) spcd_f_pm_install "shellcheck" ;; + esac + # shfmt + spcd_step "ShellFormat" + case "${SPCD_OS_ID}" in + "${SPCD_OS_ALMA}" | "${SPCD_OS_ROCKY}") ;; + "${SPCD_OS_DEBIAN}") + case "${SPCD_OS_VERSION}" in + "bullseye") ;; + *) spcd_f_pm_install "shfmt" ;; + esac + ;; + *) spcd_f_pm_install "shfmt" ;; + esac + spcd_step_out +} + +spcd_step__python_write_module() { + spcd_step "Write module" local variable value text index root for variable in \ OS_ID OS_VERSION \ @@ -1409,7 +1540,7 @@ SPCD_STEP = ${index} done } -spcd_f_py_switch() { +spcd_step__python_switch() { spcd_step "Switch" local name path name="$(basename "${SPCD_GIT_SPCD}")" @@ -1421,163 +1552,6 @@ ${SPCD_PYTHON_ALIAS} / ${name}" "${SPCD_PYTHON_ALIAS}" -m "${name}" } -# ╭───┬─────╮ -# │ f │ txt │ -# ╰───┴─────╯ - -spcd_f_txt_locale() { - local action="${1}" - local chosen="${2}" - set -- \ - "LANG" \ - "LC_CTYPE" \ - "LC_NUMERIC" \ - "LC_TIME" \ - "LC_COLLATE" \ - "LC_MONETARY" \ - "LC_MESSAGES" - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALPINE}") ;; - *) - set -- \ - "${@}" \ - "LANGUAGE" \ - "LC_PAPER" \ - "LC_NAME" \ - "LC_ADDRESS" \ - "LC_TELEPHONE" \ - "LC_MEASUREMENT" \ - "LC_IDENTIFICATION" - ;; - esac - local name - case "${action}" in - "list") - if ! locale; then - for name in "${@}"; do - spcd_os_printenv "${name}" - done - fi - ;; - "set") - spcd_f_txt_locale "list" - spcd_split - local locale long - if [ -n "${chosen}" ]; then - locale="${chosen}" - else - locale="${_SPCD_TXT_LOCALE_DEFAULT}" - fi - long="${locale}.${_SPCD_TXT_CHARSET}" - for name in "${@}"; do - if [ "${name}" != "LANGUAGE" ]; then - export "${name}=${long}" - else - export "${name}=$(spcd_f_txt_locales language "${chosen}")" - fi - done - spcd_split - spcd_f_txt_locale "list" - ;; - "show") - local regex - for name in "${@}"; do - unset regex - case "${name}" in - # LC_CTYPE - "LC_NUMERIC") regex="^\(decimal\|thousands\|grouping\)" ;; - "LC_TIME") regex="^\(day\|mon\)" ;; - # LC_COLLATE - "LC_MONETARY") - case "${SPCD_OS_ID}" in - "${SPCD_OS_ALPINE}") ;; - *) regex="^\(int_curr\|currency\|mon_\)" ;; - esac - ;; - "LC_MESSAGES") regex="^\(yes\|no\)" ;; - "LC_PAPER") regex="^\(height\|width\)" ;; - "LC_NAME") regex="^name_m" ;; - "LC_ADDRESS") regex="^\(country\|lang\)_name" ;; - "LC_TELEPHONE") regex="^int_" ;; - "LC_MEASUREMENT") regex="^measurement=" ;; - "LC_IDENTIFICATION") regex="^\(language\|territory\|title\)" ;; - *) ;; - esac - spcd_split - spcd_os_printenv "${name}" - if [ -n "${regex}" ]; then - locale --keyword-name "${name}" | grep "${regex}" - fi - done - ;; - *) ;; - esac -} - -spcd_f_txt_locales() { - local action="${1}" - local chosen="${2}" - set -- \ - "${SPCD_TXT_LOCALE_ENGLISH}" \ - "${SPCD_TXT_LOCALE_FRENCH}" - local name - case "${action}" in - "install") - spcd_f_txt_locales "list" - spcd_split - case "${SPCD_PM}" in - "${SPCD_PM_APK}") - spcd_f_pm_pkg_install "musl-locales" - export MUSL_LOCPATH="/usr/share/i18n/locales/musl" - ;; - "${SPCD_PM_APT}") - local text - for name in "${@}"; do - text="${text}\ -${name}.${_SPCD_TXT_CHARSET} ${_SPCD_TXT_CHARSET} -" - done - spcd_os_write "/etc/locale.gen" "${text}" - spcd_f_pm_pkg_install "locales" - ;; - "${SPCD_PM_DNF}") - local language - for name in "${@}"; do - language="$(echo "${name}" | cut -d _ -f 1)" - spcd_f_pm_pkg_install "glibc-langpack-${language}" - done - ;; - "${SPCD_PM_PACMAN}") spcd_f_pm_pkg_install "glibc-locales" ;; - "${SPCD_PM_ZYPPER}") spcd_f_pm_pkg_install "glibc-locale" ;; - *) ;; - esac - spcd_split - spcd_f_txt_locales "list" - ;; - "language") - local text - if [ -n "${chosen}" ]; then - text="${chosen}" - fi - for name in "${@}"; do - if [ "${name}" != "${chosen}" ]; then - if [ -n "${text}" ]; then - text="${text}:${name}" - else - text="${name}" - fi - fi - done - ;; - "list") - if ! spcd_run locale --all-locales; then - echo "No locales yet!" - fi - ;; - *) ;; - esac -} - # ╭──────╮ # │ main │ # ╰──────╯ @@ -1587,56 +1561,46 @@ spcd_main() { spcd_step_in "Environment" spcd_step_in "Defaults" spcd_step "Print defined" - spcd_f_env_list - spcd_e_default + spcd_step__environment_print + spcd_step__environment_defaults_set spcd_step "Print effective" - spcd_f_env_list + spcd_step__environment_print spcd_step_out - spcd_e_set - spcd_step "List workspace" - spcd_f_env_workspace + spcd_step__environment_set_variables + spcd_step__environment_list_workspace spcd_step_out # dns - spcd_step "DNS" - spcd_f_dns "write" + spcd_step__dns # packages spcd_step_in "Packages" - spcd_f_pm_conf_repos - spcd_f_pm_conf + spcd_step__packages_set_repositories + spcd_step__packages_set_configuration spcd_f_pm_https_trust - spcd_f_pm_pkg_update - spcd_f_pm_pkg_install - # locales - spcd_step_in "Locales" - spcd_step "Install" - spcd_f_txt_locales "install" - spcd_step "Set" - spcd_f_txt_locale "set" "${SPCD_TXT_LOCALE}" - spcd_step "Show" - spcd_f_txt_locale "show" - spcd_step_out + spcd_f_pm_update + spcd_step__packages_install_tools + spcd_step__packages_install_locales spcd_step_out # ca spcd_step_in "CA" - spcd_f_ca_install - spcd_f_ca "write" - spcd_f_ca_update + spcd_step__ca_install_package + spcd_step__ca_write_certificates + spcd_step__ca_update_certificates spcd_step_out # packages spcd_step_in "Packages" spcd_f_pm_https_verify - spcd_f_pm_pkg_update - spcd_f_pm_pkg_upgrade - spcd_f_pkg_dos2unix - spcd_f_pkg_git + spcd_f_pm_update + spcd_f_pm_upgrade + spcd_step__packages_install_dos2unix + spcd_step__packages_install_git spcd_step_out # python spcd_step_in "Python" - spcd_f_py_install - spcd_f_py_download - spcd_f_pkg - spcd_f_py_save - spcd_f_py_switch + spcd_step__python_install + spcd_step__python_modules + spcd_step__install_packages + spcd_step__python_write_module + spcd_step__python_switch } spcd_main