Compare commits
11 commits
1b312228cc
...
e3a9b87125
Author | SHA1 | Date | |
---|---|---|---|
e3a9b87125 | |||
349da5c3a8 | |||
0c88656c0f | |||
e8fc2c7f83 | |||
38108fe867 | |||
1c5a852647 | |||
da90194808 | |||
225a1def22 | |||
0108ef7a7d | |||
e277ca114a | |||
fb2b76d6cd |
2 changed files with 151 additions and 156 deletions
12
readme.md
12
readme.md
|
@ -211,10 +211,13 @@ Handle project workflows in a unified way:
|
|||
|
||||
## When
|
||||
|
||||
### Shell
|
||||
### Tasks for a 1st stable release
|
||||
|
||||
#### Shell
|
||||
|
||||
* comment
|
||||
* drawing characters constants
|
||||
* handle errors
|
||||
* packages
|
||||
* configure
|
||||
* apk
|
||||
|
@ -225,9 +228,8 @@ Handle project workflows in a unified way:
|
|||
* codecs repository
|
||||
* disable & enable https
|
||||
* test
|
||||
* underscore internals
|
||||
|
||||
### Shell → Python
|
||||
#### Shell → Python
|
||||
|
||||
* check file & variable sums
|
||||
* install system packages
|
||||
|
@ -247,7 +249,7 @@ Handle project workflows in a unified way:
|
|||
* activate
|
||||
* relay environment module name
|
||||
|
||||
### Python
|
||||
#### Python
|
||||
|
||||
* check
|
||||
* .py
|
||||
|
@ -264,7 +266,7 @@ Handle project workflows in a unified way:
|
|||
* try git repo url variable first for shunit
|
||||
* test
|
||||
|
||||
### Later
|
||||
### Task stack
|
||||
|
||||
* automate versions fetching
|
||||
* document behavior differences
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
[ -n "${SPCD_URL_UBUNTU}" ] ||
|
||||
SPCD_URL_UBUNTU="https://ubuntu.mirrors.ovh.net/ubuntu"
|
||||
|
||||
# ╭───────────╮
|
||||
# │ internals │
|
||||
# ╰───────────╯
|
||||
# ╭───╮
|
||||
# │ _ │
|
||||
# ╰───╯
|
||||
|
||||
_spcd_fill() {
|
||||
_spcd_fill__index=${1}
|
||||
|
@ -49,9 +49,9 @@ _spcd_fill() {
|
|||
unset _spcd_fill__index
|
||||
}
|
||||
|
||||
# ╭───────────┬────────╮
|
||||
# │ internals │ banner │
|
||||
# ╰───────────┴────────╯
|
||||
# ╭───┬────────╮
|
||||
# │ _ │ banner │
|
||||
# ╰───┴────────╯
|
||||
|
||||
_SPCD_BANNER_DOWN_AND_HORIZONTAL="┬"
|
||||
_SPCD_BANNER_DOWN_AND_LEFT="╮"
|
||||
|
@ -156,16 +156,16 @@ _spcd_banner_wipe() {
|
|||
__SPCD_BANNER_BOTTOM
|
||||
}
|
||||
|
||||
# ╭───────────┬───────╮
|
||||
# │ internals │ error │
|
||||
# ╰───────────┴───────╯
|
||||
# ╭───┬───────╮
|
||||
# │ _ │ error │
|
||||
# ╰───┴───────╯
|
||||
|
||||
_SPCD_ERROR_CI=1
|
||||
_SPCD_ERROR_OS=2
|
||||
|
||||
# ╭───────────┬───────╮
|
||||
# │ internals │ frame │
|
||||
# ╰───────────┴───────╯
|
||||
# ╭───┬───────╮
|
||||
# │ _ │ frame │
|
||||
# ╰───┴───────╯
|
||||
|
||||
_SPCD_FRAME_TOP="╭╴"
|
||||
_SPCD_FRAME_BOTTOM="╰╴"
|
||||
|
@ -178,9 +178,9 @@ _spcd_frame_shut() {
|
|||
echo "${_SPCD_FRAME_BOTTOM}${1}"
|
||||
}
|
||||
|
||||
# ╭───────────┬────╮
|
||||
# │ internals │ os │
|
||||
# ╰───────────┴────╯
|
||||
# ╭───┬────╮
|
||||
# │ _ │ os │
|
||||
# ╰───┴────╯
|
||||
|
||||
_spcd_os_cat() {
|
||||
if [ -n "${1}" ]; then
|
||||
|
@ -190,17 +190,17 @@ _spcd_os_cat() {
|
|||
fi
|
||||
}
|
||||
|
||||
# ╭───────────┬──────╮
|
||||
# │ internals │ rule │
|
||||
# ╰───────────┴──────╯
|
||||
# ╭───┬──────╮
|
||||
# │ _ │ rule │
|
||||
# ╰───┴──────╯
|
||||
|
||||
_SPCD_RULE_LEFT="╶"
|
||||
_SPCD_RULE_MIDDLE="─"
|
||||
_SPCD_RULE_RIGHT="╴"
|
||||
|
||||
# ╭───────────┬──────╮
|
||||
# │ internals │ step │
|
||||
# ╰───────────┴──────╯
|
||||
# ╭───┬──────╮
|
||||
# │ _ │ step │
|
||||
# ╰───┴──────╯
|
||||
|
||||
_spcd_step_wipe() {
|
||||
unset \
|
||||
|
@ -227,30 +227,6 @@ spcd_error_os() {
|
|||
exit "${_SPCD_ERROR_OS}"
|
||||
}
|
||||
|
||||
# ╭───────────┬─────╮
|
||||
# │ functions │ git │
|
||||
# ╰───────────┴─────╯
|
||||
|
||||
spcd_git_clone() {
|
||||
if [ -n "${1}" ]; then
|
||||
spcd_gc__name="$(basename "${1}")"
|
||||
spcd_gc__path="${SPCD_DL}/${spcd_gc__name}"
|
||||
spcd_gc__url="$(spcd_git_url "${1}")"
|
||||
git clone "${spcd_gc__url}" "${spcd_gc__path}"
|
||||
echo "${spcd_gc__path}"
|
||||
fi
|
||||
}
|
||||
|
||||
spcd_git_url() {
|
||||
if [ -n "${1}" ]; then
|
||||
case "${1}" in
|
||||
http*) echo "${1}" ;;
|
||||
*/*) echo "${SPCD_PROJECT_ROOT}/${1}" ;;
|
||||
*) echo "${SPCD_PROJECT_ROOT}/${SPCD_PROJECT_PATH}/${1}" ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# ╭───────────┬─────────╮
|
||||
# │ functions │ openssl │
|
||||
# ╰───────────┴─────────╯
|
||||
|
@ -363,13 +339,13 @@ spcd_step_out() {
|
|||
__SPCD_STEP_LEVEL=$((__SPCD_STEP_LEVEL - 1))
|
||||
}
|
||||
|
||||
# ╭───────╮
|
||||
# │ steps │
|
||||
# ╰───────╯
|
||||
# ╭──────╮
|
||||
# │ step │
|
||||
# ╰──────╯
|
||||
|
||||
# ╭───────┬───────────╮
|
||||
# │ steps │ constants │
|
||||
# ╰───────┴───────────╯
|
||||
# ╭──────┬───────────╮
|
||||
# │ step │ constants │
|
||||
# ╰──────┴───────────╯
|
||||
|
||||
SPCD_OS_ALMA="alma"
|
||||
SPCD_OS_ALPINE="alpine"
|
||||
|
@ -386,11 +362,11 @@ SPCD_PM_DNF="dnf"
|
|||
SPCD_PM_PACMAN="pacman"
|
||||
SPCD_PM_ZYPPER="zypper"
|
||||
|
||||
# ╭───────┬─────────────╮
|
||||
# │ steps │ environment │
|
||||
# ╰───────┴─────────────╯
|
||||
# ╭──────┬─────────────╮
|
||||
# │ step │ environment │
|
||||
# ╰──────┴─────────────╯
|
||||
|
||||
spcd_environment_set_variables() {
|
||||
spcd_step__environment_set_variables() {
|
||||
spcd_step "Set variables"
|
||||
# check script first
|
||||
[ -n "${SPCD}" ] || spcd_error_ci "SPCD"
|
||||
|
@ -579,41 +555,6 @@ ${SPCD_PROJECT_ROOT}$(basename "${GITHUB_SERVER_URL}")"
|
|||
esac
|
||||
spcd_split
|
||||
spcd_os_printenv "SPCD_PM"
|
||||
# set package manager variables
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_DNF}")
|
||||
SPCD_PM_HTTPS_PATH="/etc/dnf/dnf.conf.d/https.conf"
|
||||
SPCD_PM_HTTPS_TEXT="\
|
||||
sslverify=False
|
||||
"
|
||||
;;
|
||||
"${SPCD_PM_APK}")
|
||||
SPCD_PM_HTTPS_PATH="/etc/apk/repositories.d/https"
|
||||
SPCD_PM_HTTPS_TEXT="\
|
||||
--no-verify
|
||||
"
|
||||
;;
|
||||
"${SPCD_PM_PACMAN}")
|
||||
SPCD_PM_HTTPS_PATH="/etc/pacman.d/https.conf"
|
||||
SPCD_PM_HTTPS_TEXT="\
|
||||
SSLVerify = No
|
||||
"
|
||||
;;
|
||||
"${SPCD_PM_APT}")
|
||||
SPCD_PM_HTTPS_PATH="/etc/apt/apt.conf.d/https"
|
||||
SPCD_PM_HTTPS_TEXT="\
|
||||
Acquire::https::Verify-Peer False;
|
||||
"
|
||||
;;
|
||||
"${SPCD_PM_ZYPPER}")
|
||||
SPCD_PM_HTTPS_PATH=""
|
||||
SPCD_PM_HTTPS_TEXT="\
|
||||
"
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
spcd_split
|
||||
spcd_os_printenv "SPCD_PM_HTTPS_PATH"
|
||||
# specific
|
||||
case "${SPCD_OS_ID}" in
|
||||
"${SPCD_OS_ALMA}")
|
||||
|
@ -764,15 +705,15 @@ ${SPCD_PYTHON_VENV}/lib/${SPCD_PYTHON_COMMAND}/site-packages"
|
|||
spcd_os_printenv "SPCD_DL"
|
||||
}
|
||||
|
||||
spcd_environment_list_workspace() {
|
||||
spcd_step__environment_list_workspace() {
|
||||
spcd_step "List workspace"
|
||||
spcd_lwd__path="$(realpath .)"
|
||||
spcd_os_ls "${spcd_lwd__path}"
|
||||
}
|
||||
|
||||
# ╭───────┬───────────╮
|
||||
# │ steps │ functions │
|
||||
# ╰───────┴───────────╯
|
||||
# ╭──────┬───────────╮
|
||||
# │ step │ functions │
|
||||
# ╰──────┴───────────╯
|
||||
|
||||
spcd_clean_cache() {
|
||||
case "${SPCD_PM}" in
|
||||
|
@ -785,6 +726,37 @@ spcd_clean_cache() {
|
|||
esac
|
||||
}
|
||||
|
||||
spcd_git_clone() {
|
||||
if [ -n "${1}" ]; then
|
||||
spcd_gc__name="$(basename "${1}")"
|
||||
spcd_gc__path="${SPCD_DL}/${spcd_gc__name}"
|
||||
spcd_gc__url="$(spcd_git_url "${1}")"
|
||||
git clone "${spcd_gc__url}" "${spcd_gc__path}"
|
||||
echo "${spcd_gc__path}"
|
||||
fi
|
||||
}
|
||||
|
||||
spcd_git_url() {
|
||||
if [ -n "${1}" ]; then
|
||||
case "${1}" in
|
||||
http*) echo "${1}" ;;
|
||||
*/*) echo "${SPCD_PROJECT_ROOT}/${1}" ;;
|
||||
*) echo "${SPCD_PROJECT_ROOT}/${SPCD_PROJECT_PATH}/${1}" ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
spcd_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
|
||||
}
|
||||
|
||||
spcd_install_package() {
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_APK}") apk add "${1}" ;;
|
||||
|
@ -828,11 +800,11 @@ spcd_query_package() {
|
|||
esac
|
||||
}
|
||||
|
||||
# ╭───────┬─────╮
|
||||
# │ steps │ dns │
|
||||
# ╰───────┴─────╯
|
||||
# ╭──────┬─────╮
|
||||
# │ step │ dns │
|
||||
# ╰──────┴─────╯
|
||||
|
||||
spcd_dns() {
|
||||
spcd_step__dns() {
|
||||
spcd_step "DNS"
|
||||
while true; do
|
||||
spcd_sdr__index=$((spcd_sdr__index + 1))
|
||||
|
@ -845,11 +817,11 @@ nameserver ${spcd_sdr__value}
|
|||
spcd_os_write "/etc/resolv.conf" "${spcd_sdr__text}"
|
||||
}
|
||||
|
||||
# ╭───────┬──────────╮
|
||||
# │ steps │ packages │
|
||||
# ╰───────┴──────────╯
|
||||
# ╭──────┬──────────╮
|
||||
# │ step │ packages │
|
||||
# ╰──────┴──────────╯
|
||||
|
||||
spcd_packages_set_repositories() {
|
||||
spcd_step__packages_set_repositories() {
|
||||
spcd_step "Set repositories"
|
||||
case "${SPCD_OS_ID}" in
|
||||
"${SPCD_OS_ALMA}")
|
||||
|
@ -916,7 +888,7 @@ deb ${SPCD_URL_CHOSEN} ${SPCD_OS_VERSION}-security main universe
|
|||
esac
|
||||
}
|
||||
|
||||
spcd_packages_set_configuration() {
|
||||
spcd_step__packages_set_configuration() {
|
||||
spcd_step "Set configuration"
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_DNF}")
|
||||
|
@ -954,15 +926,35 @@ Dir::Etc::SourceParts \"\";
|
|||
esac
|
||||
}
|
||||
|
||||
spcd_packages_trust_https() {
|
||||
spcd_step__packages_trust_https() {
|
||||
spcd_step "Trust HTTPS"
|
||||
if [ -n "${SPCD_CA_1}" ] || [ "${SPCD_PM}" = "${SPCD_PM_APT}" ]; then
|
||||
spcd_os_mkdir "$(dirname "${SPCD_PM_HTTPS_PATH}")"
|
||||
spcd_os_write "${SPCD_PM_HTTPS_PATH}" "${SPCD_PM_HTTPS_TEXT}"
|
||||
spcd_pth__path="$(spcd_https_path)"
|
||||
if [ -n "${spcd_pth__path}" ]; then
|
||||
spcd_os_mkdir "$(dirname "${spcd_pth__path}")"
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_APK}") spcd_pth__text="\
|
||||
--no-verify
|
||||
" ;;
|
||||
"${SPCD_PM_APT}") spcd_pth__text="\
|
||||
Acquire::https::Verify-Peer False;
|
||||
" ;;
|
||||
"${SPCD_PM_DNF}") spcd_pth__text="\
|
||||
sslverify=False
|
||||
" ;;
|
||||
"${SPCD_PM_PACMAN}") spcd_pth__text="\
|
||||
SSLVerify = No
|
||||
" ;;
|
||||
"${SPCD_PM_ZYPPER}") ;;
|
||||
*) ;;
|
||||
esac
|
||||
[ -n "${spcd_pth__text}" ] &&
|
||||
spcd_os_write "${spcd_pth__path}" "${spcd_pth__text}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
spcd_packages_update_catalog() {
|
||||
spcd_step__packages_update_catalog() {
|
||||
spcd_step "Update catalog"
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_APK}") apk update ;;
|
||||
|
@ -974,7 +966,7 @@ spcd_packages_update_catalog() {
|
|||
esac
|
||||
}
|
||||
|
||||
spcd_packages_install_tools() {
|
||||
spcd_step__packages_install_tools() {
|
||||
spcd_step "Install tools"
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_APT}") spcd_install_package "apt-utils" ;;
|
||||
|
@ -982,16 +974,16 @@ spcd_packages_install_tools() {
|
|||
esac
|
||||
}
|
||||
|
||||
# ╭───────┬────╮
|
||||
# │ steps │ ca │
|
||||
# ╰───────┴────╯
|
||||
# ╭──────┬────╮
|
||||
# │ step │ ca │
|
||||
# ╰──────┴────╯
|
||||
|
||||
spcd_ca_install_package() {
|
||||
spcd_step__ca_install_package() {
|
||||
spcd_step "Install package"
|
||||
spcd_install_package "ca-certificates"
|
||||
}
|
||||
|
||||
spcd_ca_write_certificates() {
|
||||
spcd_step__ca_write_certificates() {
|
||||
spcd_step "Write certificates"
|
||||
case "${SPCD_OS_ID}" in
|
||||
"${SPCD_OS_ALMA}" | "${SPCD_OS_FEDORA}" | "${SPCD_OS_ROCKY}")
|
||||
|
@ -1020,7 +1012,7 @@ spcd_ca_write_certificates() {
|
|||
done
|
||||
}
|
||||
|
||||
spcd_ca_update_certificates() {
|
||||
spcd_step__ca_update_certificates() {
|
||||
spcd_step "Update certificates"
|
||||
case "${SPCD_OS_ID}" in
|
||||
"${SPCD_OS_ARCH}" | \
|
||||
|
@ -1039,16 +1031,17 @@ spcd_ca_update_certificates() {
|
|||
esac
|
||||
}
|
||||
|
||||
# ╭───────┬──────────╮
|
||||
# │ steps │ packages │
|
||||
# ╰───────┴──────────╯
|
||||
# ╭──────┬──────────╮
|
||||
# │ step │ packages │
|
||||
# ╰──────┴──────────╯
|
||||
|
||||
spcd_packages_verify_https() {
|
||||
spcd_step__packages_verify_https() {
|
||||
spcd_step "Verify HTTPS"
|
||||
spcd_os_rm "${SPCD_PM_HTTPS_PATH}"
|
||||
spcd_pvh__path="$(spcd_https_path)"
|
||||
[ -n "${spcd_pvh__path}" ] && spcd_os_rm "${spcd_pvh__path}"
|
||||
}
|
||||
|
||||
spcd_packages_upgrade_system() {
|
||||
spcd_step__packages_upgrade_system() {
|
||||
spcd_step "Upgrade system"
|
||||
case "${SPCD_PM}" in
|
||||
"${SPCD_PM_APK}") apk upgrade ;;
|
||||
|
@ -1060,21 +1053,21 @@ spcd_packages_upgrade_system() {
|
|||
esac
|
||||
}
|
||||
|
||||
spcd_packages_install_dos2unix() {
|
||||
spcd_step__packages_install_dos2unix() {
|
||||
spcd_step "Install dos2unix"
|
||||
spcd_install_package "dos2unix"
|
||||
}
|
||||
|
||||
spcd_packages_install_git() {
|
||||
spcd_step__packages_install_git() {
|
||||
spcd_step "Install Git"
|
||||
spcd_install_package "git"
|
||||
}
|
||||
|
||||
# ╭───────┬────────╮
|
||||
# │ steps │ python │
|
||||
# ╰───────┴────────╯
|
||||
# ╭──────┬────────╮
|
||||
# │ step │ python │
|
||||
# ╰──────┴────────╯
|
||||
|
||||
spcd_python_install() {
|
||||
spcd_step__python_install() {
|
||||
spcd_step "Install package"
|
||||
spcd_install_package "${SPCD_PYTHON_PACKAGE}"
|
||||
spcd_step "Link alias to command"
|
||||
|
@ -1101,7 +1094,7 @@ index-url = ${SPCD_URL_PYTHON}
|
|||
spcd_step_out
|
||||
}
|
||||
|
||||
spcd_python_modules() {
|
||||
spcd_step__python_modules() {
|
||||
spcd_step_in "Modules"
|
||||
spcd_ipm__target="${SPCD_PYTHON_VENV_PACKAGES}"
|
||||
spcd_step "List"
|
||||
|
@ -1126,7 +1119,7 @@ spcd_python_modules() {
|
|||
spcd_step_out
|
||||
}
|
||||
|
||||
spcd_install_packages() {
|
||||
spcd_step__install_packages() {
|
||||
spcd_step_in "OS packages"
|
||||
# epel
|
||||
spcd_step "EPEL"
|
||||
|
@ -1186,7 +1179,7 @@ spcd_install_packages() {
|
|||
spcd_step_out
|
||||
}
|
||||
|
||||
spcd_python_write_module() {
|
||||
spcd_step__python_write_module() {
|
||||
spcd_step "Write module"
|
||||
for spcd_wpm__variable in \
|
||||
OS_ID OS_VERSION \
|
||||
|
@ -1206,7 +1199,7 @@ SPCD_STEP = ${spcd_wpm__index}
|
|||
done
|
||||
}
|
||||
|
||||
spcd_python_switch() {
|
||||
spcd_step__python_switch() {
|
||||
spcd_step "Switch"
|
||||
spcd_stp__name="$(basename "${SPCD_GIT_MAIN}")"
|
||||
spcd_stp__path="$(realpath "${0}")"
|
||||
|
@ -1224,40 +1217,40 @@ ${SPCD_PYTHON_ALIAS} / ${spcd_stp__name}"
|
|||
spcd_main() {
|
||||
# environment
|
||||
spcd_step_in "Environment"
|
||||
spcd_environment_set_variables
|
||||
spcd_environment_list_workspace
|
||||
spcd_step__environment_set_variables
|
||||
spcd_step__environment_list_workspace
|
||||
spcd_step_out
|
||||
# dns
|
||||
spcd_dns
|
||||
spcd_step__dns
|
||||
# packages
|
||||
spcd_step_in "Packages"
|
||||
spcd_packages_set_repositories
|
||||
spcd_packages_set_configuration
|
||||
spcd_packages_trust_https
|
||||
spcd_packages_update_catalog
|
||||
spcd_packages_install_tools
|
||||
spcd_step__packages_set_repositories
|
||||
spcd_step__packages_set_configuration
|
||||
spcd_step__packages_trust_https
|
||||
spcd_step__packages_update_catalog
|
||||
spcd_step__packages_install_tools
|
||||
spcd_step_out
|
||||
# ca
|
||||
spcd_step_in "CA"
|
||||
spcd_ca_install_package
|
||||
spcd_ca_write_certificates
|
||||
spcd_ca_update_certificates
|
||||
spcd_step__ca_install_package
|
||||
spcd_step__ca_write_certificates
|
||||
spcd_step__ca_update_certificates
|
||||
spcd_step_out
|
||||
# packages
|
||||
spcd_step_in "Packages"
|
||||
spcd_packages_verify_https
|
||||
spcd_packages_update_catalog
|
||||
spcd_packages_upgrade_system
|
||||
spcd_packages_install_dos2unix
|
||||
spcd_packages_install_git
|
||||
spcd_step__packages_verify_https
|
||||
spcd_step__packages_update_catalog
|
||||
spcd_step__packages_upgrade_system
|
||||
spcd_step__packages_install_dos2unix
|
||||
spcd_step__packages_install_git
|
||||
spcd_step_out
|
||||
# python
|
||||
spcd_step_in "Python"
|
||||
spcd_python_install
|
||||
spcd_python_modules
|
||||
spcd_install_packages
|
||||
spcd_python_write_module
|
||||
spcd_python_switch
|
||||
spcd_step__python_install
|
||||
spcd_step__python_modules
|
||||
spcd_step__install_packages
|
||||
spcd_step__python_write_module
|
||||
spcd_step__python_switch
|
||||
}
|
||||
|
||||
spcd_main
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue