mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'dev' into enh-dns-autoconf
This commit is contained in:
commit
23ab7776ce
20 changed files with 154 additions and 73 deletions
|
@ -20,7 +20,7 @@ autofix-translated-strings:
|
|||
- python3 reformat_locales.py
|
||||
- '[ $(git diff -w | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- git commit -am "[CI] Reformat / remove stale translated strings" || true
|
||||
- git push -f origin "ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
|
||||
- git push -f origin "HEAD":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Reformat / remove stale translated strings" -b Yunohost:dev -p || true # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
only:
|
||||
variables:
|
||||
|
|
|
@ -43,12 +43,14 @@ ynh_replace_string () {
|
|||
local target_file
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
set +o xtrace # set +x
|
||||
|
||||
local delimit=@
|
||||
# Escape the delimiter if it's in the string.
|
||||
match_string=${match_string//${delimit}/"\\${delimit}"}
|
||||
replace_string=${replace_string//${delimit}/"\\${delimit}"}
|
||||
|
||||
set -o xtrace # set -x
|
||||
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
YNH_APP_BASEDIR=$(realpath $([[ "$(basename $0)" =~ ^backup|restore$ ]] && echo '../settings' || echo '..'))
|
||||
YNH_APP_BASEDIR=$(realpath $([[ "$(basename $0)" =~ ^backup|restore$ ]] && echo '../settings' || [[ -n "${YNH_ACTION:-}" ]] && echo '.' || echo '..' ))
|
||||
|
||||
# Handle script crashes / failures
|
||||
#
|
||||
|
@ -519,6 +519,8 @@ ynh_read_var_in_file() {
|
|||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local line_number=1
|
||||
if [[ -n "$after" ]];
|
||||
|
@ -526,6 +528,7 @@ ynh_read_var_in_file() {
|
|||
line_number=$(grep -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$line_number" ]];
|
||||
then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
@ -555,6 +558,7 @@ ynh_read_var_in_file() {
|
|||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
echo YNH_NULL
|
||||
return 0
|
||||
fi
|
||||
|
@ -570,6 +574,7 @@ ynh_read_var_in_file() {
|
|||
else
|
||||
echo "$expression"
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Set a value into heterogeneous file (yaml, json, php, python...)
|
||||
|
@ -594,6 +599,8 @@ ynh_write_var_in_file() {
|
|||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local line_number=1
|
||||
if [[ -n "$after" ]];
|
||||
|
@ -601,6 +608,7 @@ ynh_write_var_in_file() {
|
|||
line_number=$(grep -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$line_number" ]];
|
||||
then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
@ -631,6 +639,7 @@ ynh_write_var_in_file() {
|
|||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
@ -661,6 +670,7 @@ ynh_write_var_in_file() {
|
|||
fi
|
||||
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
|
||||
|
@ -727,6 +737,7 @@ ynh_secure_remove () {
|
|||
local file
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
set +o xtrace # set +x
|
||||
|
||||
local forbidden_path=" \
|
||||
/var/www \
|
||||
|
@ -754,6 +765,8 @@ ynh_secure_remove () {
|
|||
else
|
||||
ynh_print_info --message="'$file' wasn't deleted because it doesn't exist."
|
||||
fi
|
||||
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Extract a key from a plain command output
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
"iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
|
||||
"log_corrupted_md_file": "El fitxer de metadades YAML associat amb els registres està malmès: « {md_file} »\nError: {error}",
|
||||
"log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
|
||||
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre « yunohost log show {name}{name} »",
|
||||
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre « yunohost log show {name} »",
|
||||
"log_link_to_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>",
|
||||
"log_help_to_get_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre « yunohost log share {name} »",
|
||||
"log_does_exists": "No hi ha cap registre per l'operació amb el nom« {log} », utilitzeu « yunohost log list » per veure tots els registre d'operació disponibles",
|
||||
|
|
|
@ -244,7 +244,7 @@
|
|||
"dpkg_is_broken": "Du kannst das gerade nicht tun, weil dpkg/APT (der Systempaketmanager) in einem defekten Zustand zu sein scheint.... Du kannst versuchen, dieses Problem zu lösen, indem du dich über SSH verbindest und `sudo apt install --fix-broken` sowie/oder `sudo dpkg --configure -a` ausführst.",
|
||||
"global_settings_unknown_setting_from_settings_file": "Unbekannter Schlüssel in den Einstellungen: '{setting_key}', verwerfen und speichern in /etc/yunohost/settings-unknown.json",
|
||||
"log_link_to_log": "Vollständiges Log dieser Operation: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_help_to_get_log": "Um das Protokoll der Operation '{desc}' anzuzeigen, verwenden Sie den Befehl 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Um das Protokoll der Operation '{desc}' anzuzeigen, verwenden Sie den Befehl 'yunohost log show {name}'",
|
||||
"global_settings_setting_security_nginx_compatibility": "Kompatibilitäts- vs. Sicherheits-Kompromiss für den Webserver NGINX. Betrifft die Ciphers (und andere sicherheitsrelevante Aspekte)",
|
||||
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Erlaubt die Verwendung eines (veralteten) DSA-Hostkeys für die SSH-Daemon-Konfiguration",
|
||||
"log_app_remove": "Entferne die Applikation '{}'",
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
"app_already_up_to_date": "{app} is already up-to-date",
|
||||
"app_argument_choice_invalid": "Use one of these choices '{choices}' for the argument '{name}' instead of '{value}'",
|
||||
"app_argument_invalid": "Pick a valid value for the argument '{name}': {error}",
|
||||
"app_argument_password_help_keep": "Press Enter to keep the current value",
|
||||
"app_argument_password_help_optional": "Type one space to empty the password",
|
||||
"app_argument_password_no_default": "Error while parsing password argument '{name}': password argument can't have a default value for security reason",
|
||||
"app_argument_required": "Argument '{name}' is required",
|
||||
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain}{path}'), nothing to do.",
|
||||
|
@ -424,7 +426,7 @@
|
|||
"log_dyndns_subscribe": "Subscribe to a YunoHost subdomain '{}'",
|
||||
"log_dyndns_update": "Update the IP associated with your YunoHost subdomain '{}'",
|
||||
"log_help_to_get_failed_log": "The operation '{desc}' could not be completed. Please share the full log of this operation using the command 'yunohost log share {name}' to get help",
|
||||
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log show {name}'",
|
||||
"log_letsencrypt_cert_install": "Install a Let's Encrypt certificate on '{}' domain",
|
||||
"log_letsencrypt_cert_renew": "Renew '{}' Let's Encrypt certificate",
|
||||
"log_link_to_failed_log": "Could not complete the operation '{desc}'. Please provide the full log of this operation by <a href=\"#/tools/logs/{name}\">clicking here</a> to get help",
|
||||
|
|
|
@ -326,7 +326,7 @@
|
|||
"log_dyndns_subscribe": "Aboni al YunoHost-subdominio '{}'",
|
||||
"password_too_simple_4": "La pasvorto bezonas almenaŭ 12 signojn kaj enhavas ciferon, majuskle, pli malaltan kaj specialajn signojn",
|
||||
"regenconf_file_updated": "Agordodosiero '{conf}' ĝisdatigita",
|
||||
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log show {name}'",
|
||||
"global_settings_setting_security_nginx_compatibility": "Kongruo vs sekureca kompromiso por la TTT-servilo NGINX. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
|
||||
"restore_complete": "Restarigita",
|
||||
"hook_exec_failed": "Ne povis funkcii skripto: {path}",
|
||||
|
|
|
@ -325,7 +325,7 @@
|
|||
"log_does_exists": "No existe ningún registro de actividades con el nombre '{log}', ejecute 'yunohost log list' para ver todos los registros de actividades disponibles",
|
||||
"log_help_to_get_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, comparta el registro completo de esta operación ejecutando la orden «yunohost log share {name}»",
|
||||
"log_link_to_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, proporcione el registro completo de esta operación <a href=\"#/tools/logs/{name}\">pulsando aquí</a>",
|
||||
"log_help_to_get_log": "Para ver el registro de la operación «{desc}», ejecute la orden «yunohost log show {name}{name}»",
|
||||
"log_help_to_get_log": "Para ver el registro de la operación «{desc}», ejecute la orden «yunohost log show {name}»",
|
||||
"log_link_to_log": "Registro completo de esta operación: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
|
||||
"log_corrupted_md_file": "El archivo de metadatos YAML asociado con el registro está dañado: «{md_file}\nError: {error}»",
|
||||
"hook_json_return_error": "No se pudo leer la respuesta del gancho {path}. Error: {msg}. Contenido sin procesar: {raw_content}",
|
||||
|
|
|
@ -500,7 +500,7 @@
|
|||
"log_does_exists": "هیچ گزارش عملیاتی با نام '{log}' وجود ندارد ، برای مشاهده همه گزارش عملیّات های موجود در خط فرمان از دستور 'yunohost log list' استفاده کنید",
|
||||
"log_help_to_get_failed_log": "عملیات '{desc}' کامل نشد. لطفاً برای دریافت راهنمایی و کمک ، گزارش کامل این عملیات را با استفاده از دستور 'yunohost log share {name}' به اشتراک بگذارید",
|
||||
"log_link_to_failed_log": "عملیّات '{desc}' کامل نشد. لطفاً گزارش کامل این عملیات را ارائه دهید بواسطه <a href=\"#/tools/logs/{name}\">اینجا را کلیک کنید</a> برای دریافت کمک",
|
||||
"log_help_to_get_log": "برای مشاهده گزارش عملیات '{desc}'، از دستور 'yunohost log show {name}{name}' استفاده کنید",
|
||||
"log_help_to_get_log": "برای مشاهده گزارش عملیات '{desc}'، از دستور 'yunohost log show {name}' استفاده کنید",
|
||||
"log_link_to_log": "گزارش کامل این عملیات: <a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_corrupted_md_file": "فایل فوق داده YAML مربوط به گزارش ها آسیب دیده است: '{md_file}\nخطا: {error} '",
|
||||
"ldap_server_is_down_restart_it": "سرویس LDAP خاموش است ، سعی کنید آن را دوباره راه اندازی کنید...",
|
||||
|
|
|
@ -251,7 +251,7 @@
|
|||
"experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas l'utiliser à moins que vous ne sachiez ce que vous faites.",
|
||||
"log_corrupted_md_file": "Le fichier YAML de métadonnées associé aux logs est corrompu : '{md_file}'\nErreur : {error}",
|
||||
"log_link_to_log": "Journal complet de cette opération : '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
|
||||
"log_help_to_get_log": "Pour voir le journal de cette opération '{desc}', utilisez la commande 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Pour voir le journal de cette opération '{desc}', utilisez la commande 'yunohost log show {name}'",
|
||||
"log_link_to_failed_log": "L'opération '{desc}' a échoué ! Pour obtenir de l'aide, merci de partager le journal de l'opération en <a href=\"#/tools/logs/{name}\">cliquant ici</a>",
|
||||
"log_help_to_get_failed_log": "L'opération '{desc}' a échoué ! Pour obtenir de l'aide, merci de partager le journal de l'opération en utilisant la commande 'yunohost log share {name}'",
|
||||
"log_does_exists": "Il n'y a pas de journal des opérations avec le nom '{log}', utilisez 'yunohost log list' pour voir tous les journaux d'opérations disponibles",
|
||||
|
|
|
@ -358,7 +358,7 @@
|
|||
"global_settings_setting_security_webadmin_allowlist_enabled": "Permitir que só algúns IPs accedan á webadmin.",
|
||||
"disk_space_not_sufficient_update": "Non hai espazo suficiente no disco para actualizar esta aplicación",
|
||||
"disk_space_not_sufficient_install": "Non queda espazo suficiente no disco para instalar esta aplicación",
|
||||
"log_help_to_get_log": "Para ver o rexistro completo da operación '{desc}', usa o comando 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Para ver o rexistro completo da operación '{desc}', usa o comando 'yunohost log show {name}'",
|
||||
"log_link_to_log": "Rexistro completo desta operación: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_corrupted_md_file": "O ficheiro YAML con metadatos asociado aos rexistros está danado: '{md_file}\nErro: {error}'",
|
||||
"iptables_unavailable": "Non podes andar remexendo en iptables aquí. Ou ben estás nun contedor ou o teu kernel non ten soporte para isto",
|
||||
|
|
|
@ -249,7 +249,7 @@
|
|||
"good_practices_about_admin_password": "Stai per impostare una nuova password di amministratore. La password deve essere almeno di 8 caratteri - anche se è buona pratica utilizzare password più lunghe (es. una frase, una serie di parole) e/o utilizzare vari tipi di caratteri (maiuscole, minuscole, numeri e simboli).",
|
||||
"log_corrupted_md_file": "Il file dei metadati YAML associato con i registri è danneggiato: '{md_file}'\nErrore: {error}",
|
||||
"log_link_to_log": "Registro completo di questa operazione: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_help_to_get_log": "Per vedere il registro dell'operazione '{desc}', usa il comando 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Per vedere il registro dell'operazione '{desc}', usa il comando 'yunohost log show {name}'",
|
||||
"global_settings_setting_security_postfix_compatibility": "Bilanciamento tra compatibilità e sicurezza per il server Postfix. Riguarda gli algoritmi di cifratura (e altri aspetti legati alla sicurezza)",
|
||||
"log_link_to_failed_log": "Impossibile completare l'operazione '{desc}'! Per ricevere aiuto, per favore fornisci il registro completo dell'operazione <a href=\"#/tools/logs/{name}\">cliccando qui</a>",
|
||||
"log_help_to_get_failed_log": "L'operazione '{desc}' non può essere completata. Per ottenere aiuto, per favore condividi il registro completo dell'operazione utilizzando il comando 'yunohost log share {name}'",
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
"domain_deletion_failed": "Kunne ikke slette domene",
|
||||
"domain_dyndns_already_subscribed": "Du har allerede abonnement på et DynDNS-domene",
|
||||
"log_link_to_log": "Full logg for denne operasjonen: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_help_to_get_log": "For å vise loggen for operasjonen '{desc}', bruk kommandoen 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "For å vise loggen for operasjonen '{desc}', bruk kommandoen 'yunohost log show {name}'",
|
||||
"log_user_create": "Legg til '{}' bruker",
|
||||
"app_change_url_success": "{app} nettadressen er nå {domain}{path}",
|
||||
"app_install_failed": "Kunne ikke installere {app}: {error}"
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
"experimental_feature": "Atencion : aquesta foncionalitat es experimentala e deu pas èsser considerada coma establa, deuriatz pas l’utilizar levat que sapiatz çò que fasètz.",
|
||||
"log_corrupted_md_file": "Lo fichièr YAML de metadonadas ligat als jornals d’audit es damatjat : « {md_file} »\nError : {error}",
|
||||
"log_link_to_log": "Jornal complèt d’aquesta operacion : <a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>",
|
||||
"log_help_to_get_log": "Per veire lo jornal d’aquesta operacion « {desc} », utilizatz la comanda « yunohost log show {name}{name} »",
|
||||
"log_help_to_get_log": "Per veire lo jornal d’aquesta operacion « {desc} », utilizatz la comanda « yunohost log show {name} »",
|
||||
"log_link_to_failed_log": "L’operacion « {desc} » a pas capitat ! Per obténer d’ajuda, mercés <a href=\"#/tools/logs/{name}\"> de fornir lo jornal complèt de l’operacion</a>",
|
||||
"log_help_to_get_failed_log": "L’operacion « {desc} » a pas reüssit ! Per obténer d’ajuda, mercés de partejar lo jornal d’audit complèt d’aquesta operacion en utilizant la comanda « yunohost log share {name} »",
|
||||
"log_does_exists": "I a pas cap de jornal d’audit per l’operacion amb lo nom « {log} », utilizatz « yunohost log list » per veire totes los jornals d’operacion disponibles",
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
"log_does_exists": "Немає журналу операцій з назвою '{log}', використовуйте 'yunohost log list', щоб подивитися всі доступні журнали операцій",
|
||||
"log_help_to_get_failed_log": "Операція '{desc}' не може бути завершена. Будь ласка, поділіться повним журналом цієї операції, використовуючи команду 'yunohost log share {name}', щоб отримати допомогу",
|
||||
"log_link_to_failed_log": "Не вдалося завершити операцію '{desc}'. Будь ласка, надайте повний журнал цієї операції, <a href=\"#/tools/logs/{name}\">натиснувши тут</a>, щоб отримати допомогу",
|
||||
"log_help_to_get_log": "Щоб переглянути журнал операції '{desc}', використовуйте команду 'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "Щоб переглянути журнал операції '{desc}', використовуйте команду 'yunohost log show {name}'",
|
||||
"log_link_to_log": "Повний журнал цієї операції: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_corrupted_md_file": "Файл метаданих YAML, пов'язаний з журналами, пошкоджено: '{md_file}\nПомилка: {error}'",
|
||||
"iptables_unavailable": "Ви не можете грати з iptables тут. Ви перебуваєте або в контейнері, або ваше ядро не підтримує його",
|
||||
|
|
|
@ -511,7 +511,7 @@
|
|||
"log_does_exists": "没有名称为'{log}'的操作日志,请使用 'yunohost log list' 查看所有可用的操作日志",
|
||||
"log_help_to_get_failed_log": "操作'{desc}'无法完成。请使用命令'yunohost log share {name}' 共享此操作的完整日志以获取帮助",
|
||||
"log_link_to_failed_log": "无法完成操作 '{desc}'。请通过<a href=\"#/tools/logs/{name}\">单击此处</a>提供此操作的完整日志以获取帮助",
|
||||
"log_help_to_get_log": "要查看操作'{desc}'的日志,请使用命令'yunohost log show {name}{name}'",
|
||||
"log_help_to_get_log": "要查看操作'{desc}'的日志,请使用命令'yunohost log show {name}'",
|
||||
"log_link_to_log": "此操作的完整日志: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_corrupted_md_file": "与日志关联的YAML元数据文件已损坏: '{md_file}\n错误: {error}'",
|
||||
"iptables_unavailable": "你不能在这里使用iptables。你要么在一个容器中,要么你的内核不支持它",
|
||||
|
|
|
@ -1652,25 +1652,34 @@ def app_action_run(operation_logger, app, action, args=None):
|
|||
)
|
||||
env_dict["YNH_ACTION"] = action
|
||||
|
||||
_, path = tempfile.mkstemp()
|
||||
tmp_workdir_for_app = _make_tmp_workdir_for_app(app=app)
|
||||
_, action_script = tempfile.mkstemp(dir=tmp_workdir_for_app)
|
||||
|
||||
with open(path, "w") as script:
|
||||
with open(action_script, "w") as script:
|
||||
script.write(action_declaration["command"])
|
||||
|
||||
os.chmod(path, 700)
|
||||
|
||||
if action_declaration.get("cwd"):
|
||||
cwd = action_declaration["cwd"].replace("$app", app)
|
||||
else:
|
||||
cwd = os.path.join(APPS_SETTING_PATH, app)
|
||||
cwd = tmp_workdir_for_app
|
||||
|
||||
# FIXME: this should probably be ran in a tmp workdir...
|
||||
retcode = hook_exec(
|
||||
path,
|
||||
env=env_dict,
|
||||
chdir=cwd,
|
||||
user=action_declaration.get("user", "root"),
|
||||
)[0]
|
||||
try:
|
||||
retcode = hook_exec(
|
||||
action_script,
|
||||
env=env_dict,
|
||||
chdir=cwd,
|
||||
user=action_declaration.get("user", "root"),
|
||||
)[0]
|
||||
# Calling hook_exec could fail miserably, or get
|
||||
# manually interrupted (by mistake or because script was stuck)
|
||||
# In that case we still want to delete the tmp work dir
|
||||
except (KeyboardInterrupt, EOFError, Exception):
|
||||
retcode = -1
|
||||
import traceback
|
||||
|
||||
logger.error(m18n.n("unexpected_error", error="\n" + traceback.format_exc()))
|
||||
finally:
|
||||
shutil.rmtree(tmp_workdir_for_app)
|
||||
|
||||
if retcode not in action_declaration.get("accepted_return_codes", [0]):
|
||||
msg = "Error while executing action '%s' of app '%s': return code %s" % (
|
||||
|
@ -1681,8 +1690,6 @@ def app_action_run(operation_logger, app, action, args=None):
|
|||
operation_logger.error(msg)
|
||||
raise YunohostError(msg, raw_msg=True)
|
||||
|
||||
os.remove(path)
|
||||
|
||||
operation_logger.success()
|
||||
return logger.success("Action successed!")
|
||||
|
||||
|
@ -1760,7 +1767,6 @@ class AppConfigPanel(ConfigPanel):
|
|||
default_script = """#!/bin/bash
|
||||
source /usr/share/yunohost/helpers
|
||||
ynh_abort_if_errors
|
||||
final_path=$(ynh_app_setting_get $app final_path)
|
||||
ynh_app_config_run $1
|
||||
"""
|
||||
write_to_file(config_script, default_script)
|
||||
|
@ -1768,11 +1774,13 @@ ynh_app_config_run $1
|
|||
# Call config script to extract current values
|
||||
logger.debug(f"Calling '{action}' action from config script")
|
||||
app_id, app_instance_nb = _parse_app_instance_name(self.app)
|
||||
settings = _get_app_settings(app_id)
|
||||
env.update(
|
||||
{
|
||||
"app_id": app_id,
|
||||
"app": self.app,
|
||||
"app_instance_nb": str(app_instance_nb),
|
||||
"final_path": settings.get("final_path", "")
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -2173,6 +2181,13 @@ def _set_default_ask_questions(arguments):
|
|||
key = "app_manifest_%s_ask_%s" % (script_name, arg["name"])
|
||||
arg["ask"] = m18n.n(key)
|
||||
|
||||
# Also it in fact doesn't make sense for any of those questions to have an example value nor a default value...
|
||||
if arg.get("type") in ["domain", "user", "password"]:
|
||||
if "example" in arg:
|
||||
del arg["example"]
|
||||
if "default" in arg:
|
||||
del arg["domain"]
|
||||
|
||||
return arguments
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,13 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
|
|||
logs = list(reversed(sorted(logs)))
|
||||
|
||||
if limit is not None:
|
||||
logs = logs[:limit]
|
||||
if with_suboperations:
|
||||
logs = logs[:limit]
|
||||
else:
|
||||
# If we displaying only parent, we are still gonna load up to limit * 5 logs
|
||||
# because many of them are suboperations which are not gonna be kept
|
||||
# Yet we still want to obtain ~limit number of logs
|
||||
logs = logs[:limit * 5]
|
||||
|
||||
for log in logs:
|
||||
|
||||
|
@ -122,6 +128,9 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
|
|||
else:
|
||||
operations = [o for o in operations.values()]
|
||||
|
||||
if limit:
|
||||
operations = operations[:limit]
|
||||
|
||||
operations = list(reversed(sorted(operations, key=lambda o: o["name"])))
|
||||
# Reverse the order of log when in cli, more comfortable to read (avoid
|
||||
# unecessary scrolling)
|
||||
|
@ -151,26 +160,37 @@ def log_show(
|
|||
filter_irrelevant = True
|
||||
|
||||
if filter_irrelevant:
|
||||
filters = [
|
||||
r"set [+-]x$",
|
||||
r"set [+-]o xtrace$",
|
||||
r"local \w+$",
|
||||
r"local legacy_args=.*$",
|
||||
r".*Helper used in legacy mode.*",
|
||||
r"args_array=.*$",
|
||||
r"local -A args_array$",
|
||||
r"ynh_handle_getopts_args",
|
||||
r"ynh_script_progression",
|
||||
]
|
||||
|
||||
def _filter(lines):
|
||||
filters = [
|
||||
r"set [+-]x$",
|
||||
r"set [+-]o xtrace$",
|
||||
r"set [+-]o errexit$",
|
||||
r"set [+-]o nounset$",
|
||||
r"trap '' EXIT",
|
||||
r"local \w+$",
|
||||
r"local exit_code=(1|0)$",
|
||||
r"local legacy_args=.*$",
|
||||
r"local -A args_array$",
|
||||
r"args_array=.*$",
|
||||
r"ret_code=1",
|
||||
r".*Helper used in legacy mode.*",
|
||||
r"ynh_handle_getopts_args",
|
||||
r"ynh_script_progression",
|
||||
r"sleep 0.5",
|
||||
r"'\[' (1|0) -eq (1|0) '\]'$",
|
||||
r"\[?\['? -n '' '?\]\]?$",
|
||||
r"rm -rf /var/cache/yunohost/download/$",
|
||||
r"type -t ynh_clean_setup$",
|
||||
r"DEBUG - \+ echo '",
|
||||
r"DEBUG - \+ exit (1|0)$",
|
||||
]
|
||||
filters = [re.compile(f) for f in filters]
|
||||
return [line for line in lines if not any(f.search(line.strip()) for f in filters)]
|
||||
else:
|
||||
filters = []
|
||||
def _filter(lines):
|
||||
return lines
|
||||
|
||||
def _filter_lines(lines, filters=[]):
|
||||
|
||||
filters = [re.compile(f) for f in filters]
|
||||
return [
|
||||
line for line in lines if not any(f.search(line.strip()) for f in filters)
|
||||
]
|
||||
|
||||
# Normalize log/metadata paths and filenames
|
||||
abs_path = path
|
||||
|
@ -209,7 +229,7 @@ def log_show(
|
|||
content += "\n============\n\n"
|
||||
if os.path.exists(log_path):
|
||||
actual_log = read_file(log_path)
|
||||
content += "\n".join(_filter_lines(actual_log.split("\n"), filters))
|
||||
content += "\n".join(_filter(actual_log.split("\n")))
|
||||
|
||||
url = yunopaste(content)
|
||||
|
||||
|
@ -282,13 +302,13 @@ def log_show(
|
|||
if os.path.exists(log_path):
|
||||
from yunohost.service import _tail
|
||||
|
||||
if number and filters:
|
||||
if number and filter_irrelevant:
|
||||
logs = _tail(log_path, int(number * 4))
|
||||
elif number:
|
||||
logs = _tail(log_path, int(number))
|
||||
else:
|
||||
logs = read_file(log_path)
|
||||
logs = _filter_lines(logs, filters)
|
||||
logs = list(_filter(logs))
|
||||
if number:
|
||||
logs = logs[-number:]
|
||||
infos["log_path"] = log_path
|
||||
|
|
|
@ -552,7 +552,7 @@ def test_question_password_input_test_ask():
|
|||
prompt.assert_called_with(
|
||||
message=ask_text,
|
||||
is_password=True,
|
||||
confirm=True,
|
||||
confirm=False,
|
||||
prefill="",
|
||||
is_multiline=False,
|
||||
)
|
||||
|
|
|
@ -203,7 +203,6 @@ class ConfigPanel:
|
|||
"panels": {
|
||||
"properties": ["name", "services", "actions", "help"],
|
||||
"default": {
|
||||
"name": "",
|
||||
"services": [],
|
||||
"actions": {"apply": {"en": "Apply"}},
|
||||
},
|
||||
|
@ -277,7 +276,9 @@ class ConfigPanel:
|
|||
continue
|
||||
subnode = convert(value, subnode_type)
|
||||
subnode["id"] = key
|
||||
if node_type == "sections":
|
||||
if node_type == "toml":
|
||||
subnode.setdefault("name", {"en": key.capitalize()})
|
||||
elif node_type == "sections":
|
||||
subnode["name"] = key # legacy
|
||||
subnode.setdefault("optional", toml_node.get("optional", True))
|
||||
node.setdefault(subnode_type, []).append(subnode)
|
||||
|
@ -364,7 +365,8 @@ class ConfigPanel:
|
|||
display_header(f"\n{'='*40}\n>>>> {name}\n{'='*40}")
|
||||
continue
|
||||
name = _value_for_locale(section["name"])
|
||||
display_header(f"\n# {name}")
|
||||
if name:
|
||||
display_header(f"\n# {name}")
|
||||
|
||||
# Check and ask unanswered questions
|
||||
self.new_values.update(
|
||||
|
@ -473,6 +475,20 @@ class Question(object):
|
|||
def normalize(value, option={}):
|
||||
return value
|
||||
|
||||
def _prompt(self, text):
|
||||
prefill = ""
|
||||
if self.current_value is not None:
|
||||
prefill = self.humanize(self.current_value, self)
|
||||
elif self.default is not None:
|
||||
prefill = self.humanize(self.default, self)
|
||||
self.value = Moulinette.prompt(
|
||||
message=text,
|
||||
is_password=self.hide_user_input_in_prompt,
|
||||
confirm=False, # We doesn't want to confirm this kind of password like in webadmin
|
||||
prefill=prefill,
|
||||
is_multiline=(self.type == "text"),
|
||||
)
|
||||
|
||||
def ask_if_needed(self):
|
||||
for i in range(5):
|
||||
# Display question if no value filled or if it's a readonly message
|
||||
|
@ -480,20 +496,8 @@ class Question(object):
|
|||
text_for_user_input_in_cli = self._format_text_for_user_input_in_cli()
|
||||
if getattr(self, "readonly", False):
|
||||
Moulinette.display(text_for_user_input_in_cli)
|
||||
|
||||
elif self.value is None:
|
||||
prefill = ""
|
||||
if self.current_value is not None:
|
||||
prefill = self.humanize(self.current_value, self)
|
||||
elif self.default is not None:
|
||||
prefill = self.humanize(self.default, self)
|
||||
self.value = Moulinette.prompt(
|
||||
message=text_for_user_input_in_cli,
|
||||
is_password=self.hide_user_input_in_prompt,
|
||||
confirm=self.hide_user_input_in_prompt,
|
||||
prefill=prefill,
|
||||
is_multiline=(self.type == "text"),
|
||||
)
|
||||
self._prompt(text_for_user_input_in_cli)
|
||||
|
||||
# Apply default value
|
||||
class_default = getattr(self, "default_value", None)
|
||||
|
@ -529,7 +533,7 @@ class Question(object):
|
|||
raise YunohostValidationError("app_argument_required", name=self.name)
|
||||
|
||||
# we have an answer, do some post checks
|
||||
if self.value is not None:
|
||||
if self.value not in [None, ""]:
|
||||
if self.choices and self.value not in self.choices:
|
||||
self._raise_invalid_answer()
|
||||
if self.pattern and not re.match(self.pattern["regexp"], str(self.value)):
|
||||
|
@ -547,13 +551,13 @@ class Question(object):
|
|||
choices=", ".join(self.choices),
|
||||
)
|
||||
|
||||
def _format_text_for_user_input_in_cli(self):
|
||||
def _format_text_for_user_input_in_cli(self, column=False):
|
||||
text_for_user_input_in_cli = _value_for_locale(self.ask)
|
||||
|
||||
if self.choices:
|
||||
text_for_user_input_in_cli += " [{0}]".format(" | ".join(self.choices))
|
||||
|
||||
if self.help:
|
||||
if self.help or column:
|
||||
text_for_user_input_in_cli += ":\033[m"
|
||||
if self.help:
|
||||
text_for_user_input_in_cli += "\n - "
|
||||
|
@ -694,6 +698,23 @@ class PasswordQuestion(Question):
|
|||
|
||||
assert_password_is_strong_enough("user", self.value)
|
||||
|
||||
def _format_text_for_user_input_in_cli(self):
|
||||
need_column = self.current_value or self.optional
|
||||
text_for_user_input_in_cli = super()._format_text_for_user_input_in_cli(need_column)
|
||||
if self.current_value:
|
||||
text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_keep")
|
||||
if self.optional:
|
||||
text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_optional")
|
||||
|
||||
return text_for_user_input_in_cli
|
||||
|
||||
def _prompt(self, text):
|
||||
super()._prompt(text)
|
||||
if self.current_value and self.value == "":
|
||||
self.value = self.current_value
|
||||
elif self.value == " ":
|
||||
self.value = ""
|
||||
|
||||
|
||||
class PathQuestion(Question):
|
||||
argument_type = "path"
|
||||
|
@ -802,6 +823,14 @@ class UserQuestion(Question):
|
|||
|
||||
super().__init__(question, user_answers)
|
||||
self.choices = user_list()["users"]
|
||||
|
||||
if not self.choices:
|
||||
raise YunohostValidationError(
|
||||
"app_argument_invalid",
|
||||
name=self.name,
|
||||
error="You should create a YunoHost user first."
|
||||
)
|
||||
|
||||
if self.default is None:
|
||||
root_mail = "root@%s" % _get_maindomain()
|
||||
for user in self.choices.keys():
|
||||
|
|
Loading…
Add table
Reference in a new issue