début migration nulib
This commit is contained in:
parent
662bdb92dd
commit
eba69bea41
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
# Utiliser 'udir --help-vars' pour une description de la signification des
|
||||
# variables suivantes:
|
||||
udir_desc="librairies de base pour scripts bash, awk, php, python"
|
||||
udir_note=""
|
||||
udir_types=(uinst)
|
||||
uinc=release
|
||||
uinc_options=()
|
||||
uinc_args=()
|
||||
preconfig_scripts=()
|
||||
configure_variables=(dest)
|
||||
configure_dest_for=(lib/profile.d/nucore)
|
||||
config_scripts=(lib/uinst/conf)
|
||||
install_profiles=true
|
||||
profiledir=lib/profile.d
|
||||
bashrcdir=lib/bashrc.d
|
||||
defaultdir=lib/default
|
||||
workdir_rsync_options=()
|
||||
workdir_excludes=()
|
||||
workdir_includes=()
|
||||
copy_files=true
|
||||
destdir=/opt
|
||||
destdir_override_userhost=
|
||||
destdir_ssh=
|
||||
destdir_force_remote=
|
||||
srcdir=.
|
||||
files=()
|
||||
owner=root:
|
||||
modes=(u=rwX,g=rX,o=rX)
|
||||
root_scripts=(lib/uinst/rootconf)
|
|
@ -0,0 +1,176 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.args "Fonctions de base: analyse d'arguments"
|
||||
require: base.arr
|
||||
|
||||
function: myargs_local "Afficher des commandes pour rendre locales des variables utilisées par myargs()
|
||||
|
||||
Cela permet d'utiliser myargs() à l'intérieur d'une fonction. Par défaut, la génération automatique de l'autocomplete est désactivée."
|
||||
function myargs_local() {
|
||||
# par défaut, désactiver génération de autocomplete
|
||||
echo "local NUCORE_ARGS_HELP_DESC NUCORE_ARGS_HELP_USAGE NUCORE_ARGS_HELP_OPTIONS args"
|
||||
echo "local NUCORE_ARGS_DISABLE_AC=1"
|
||||
echo "local NUCORE_ARGS_ONERROR_RETURN=1"
|
||||
}
|
||||
|
||||
function: myargs: "Débuter la description des arguments reconnus par ce script.
|
||||
|
||||
Arguments
|
||||
: \$1 est un résumé de l'objet de ce script
|
||||
: \$2 est le nom du script s'il est différent de \$MYNAME
|
||||
|
||||
Le mode opératoire est généralement le suivant:
|
||||
~~~
|
||||
myargs:
|
||||
desc \"faire un traitement\"
|
||||
usage \"MYNAME [options] <args>\"
|
||||
arg -o:,--output:file output= \"spécifier le fichier destination\"
|
||||
arg -h:,--host:host hosts+ \"spécifier les hôtes concernés\"
|
||||
arg -c,--count count=1
|
||||
parse \"\$@\"; set -- \"\${args[@]}\"
|
||||
~~~"
|
||||
function myargs:() {
|
||||
NUCORE_ARGS_HELP_DESC=
|
||||
NUCORE_ARGS_HELP_USAGE=
|
||||
NUCORE_ARGS_HELP_OPTIONS=()
|
||||
args=()
|
||||
function desc() { myargs_desc "$@"; }
|
||||
function usage() { myargs_usage "$@"; }
|
||||
function arg() { myargs_add "$@"; }
|
||||
function parse() { myargs_parse "$@"; }
|
||||
}
|
||||
|
||||
function: myargs_desc ""
|
||||
function myargs_desc() {
|
||||
NUCORE_ARGS_HELP_DESC="$*"
|
||||
}
|
||||
|
||||
function: myargs_usage ""
|
||||
function myargs_usage() {
|
||||
NUCORE_ARGS_HELP_USAGE="$*"
|
||||
}
|
||||
|
||||
function: myargs_add "Ajouter une définition d'option
|
||||
|
||||
Syntaxes
|
||||
: arg MODE
|
||||
: arg [MODE] -OPTIONS ACTION DESC
|
||||
: arg [MODE] VARIABLE DESC
|
||||
|
||||
MODE peut être l'un des caractères '+', '-', '%' et a un effet sur l'analyse
|
||||
entière de la ligne de commande
|
||||
* Les caractères '+' et '-' influent sur la méthode d'analyse. Par défaut, les
|
||||
options sont valides n'importe où sur la ligne de commande. Avec '+',
|
||||
l'analyse s'arrête au premier argument qui n'est pas une option. Avec '-', les
|
||||
options sont valides n'importe ou sur la ligne de commande, mais les arguments
|
||||
ne sont pas réordonnés, et apparaissent dans l'ordre de leur mention.
|
||||
* Le caractère '%' demande que toutes les variables mentionnées à partir de ce
|
||||
moment soient initialisées. Elle sont garanties d'être vides.
|
||||
|
||||
Avec la première syntaxe, on définit précisément l'option. Deux formes sont
|
||||
supportées. La forme détermine le type d'action
|
||||
* Avec la forme '-OPT VAR[=VALUE]', OPT est une description d'option, VAR un nom
|
||||
de variable à mettre à jour, et VALUE une valeur éventuelle pour les options
|
||||
sans argument. Si plusieurs options sont mentionnées, séparées par des
|
||||
virgules, alors tous les options partagent les mêmes paramètres.
|
||||
|
||||
OPT peut être de la forme '-o' ou '--longopt' pour des options sans arguments.
|
||||
Dans ce cas, VAR obtient le nombre de fois que l'option est mentionnée (vide
|
||||
pour aucune mention, '1' pour une seule mention, etc.), sauf si on utilise la
|
||||
forme VAR=VALUE, auquel cas la variable obtient la valeur VALUE, et le nombre
|
||||
d'occurences de l'option n'est pas compté.
|
||||
|
||||
Pour faciliter la lecture:
|
||||
* '--longopt .' est équivalent à '--longopt longopt'
|
||||
* '--longopt: .' est équivalent à '--longopt: longopt='
|
||||
|
||||
Avec les formes '-o:' et '--longopt:', l'option prend un argument obligatoire.
|
||||
Avec les formes '-o::' et '--longopt::', l'option prend un argument facultatif
|
||||
(dans ce cas, la valeur de l'option sur la ligne de commande doit
|
||||
obligatoirement être collée à l'option.)
|
||||
|
||||
Si ces options sont mentionnées plusieurs fois sur la ligne de commande, alors
|
||||
la variable de destination est un tableau qui contient toutes les valeurs. Le
|
||||
traitement de la valeur d'une variable dépend de la forme utilisée.
|
||||
* Avec une option sans argument, le comportement est celui décrit ci-dessus.
|
||||
* Avec une option qui prend des arguments, la forme '-o: VAR' considère que
|
||||
VAR est un tableau qui contiendra toutes les valeurs mentionnées dans les
|
||||
options. Avec la forme '-o: VAR=', la variable n'est pas un tableau et
|
||||
contient toujours la dernière valeur spécifiée.
|
||||
* Dans la forme 'opt \$cmd', la commande cmd est executée avec eval *dès* que
|
||||
l'option est rencontrée. La variable option_ contient l'option, e.g. '-o' ou
|
||||
'--longopt'. Le cas échéant, la variable value_ contient la valeur de
|
||||
l'option. La fonction 'set@ NAME' met à jour la variable NAME, soit en lui
|
||||
donnant la valeur \$value_, soit en l'incrémentant, suivant le type d'option.
|
||||
La fonction 'inc@ NAME' incrémente la variable NAME, 'res@ NAME [VALUE]'
|
||||
initialise la variable à la valeur VALUE, 'add@ NAME [VALUE]' ajoute VALUE à
|
||||
la fin du tableau NAME. Par défaut, VALUE vaut \$value_
|
||||
|
||||
Avec la deuxième syntaxe, l'option est déterminée sur la base du nom de la
|
||||
variable.
|
||||
* Une variable de la forme 'sansarg' est pour une option simple qui ne prend pas
|
||||
d'argument
|
||||
* Une variable de la forme 'avecarg=[default-value]' est pour une option qui
|
||||
prend un argument.
|
||||
L'option générée est une option longue. En l'occurence, les options générées
|
||||
sont respectivement '--sansarg' et '--avecarg:'
|
||||
Les variables et les options sont toujours en minuscule. Pour les variables, le
|
||||
caractère '-' est remplacé par '_'. Si une option contient une lettre en
|
||||
majuscule, l'option courte correspondante à cette lettre sera aussi reconnue.
|
||||
|
||||
"
|
||||
function myargs_add() {
|
||||
# description des options
|
||||
array_add args "${@:1:2}"
|
||||
# puis construire la description de l'option pour l'aide
|
||||
local -a os; local o odesc
|
||||
array_split os "$1" ,
|
||||
for o in "${os[@]}"; do
|
||||
o="${o%%:*}"
|
||||
[ -n "$odesc" ] && odesc="$odesc, "
|
||||
odesc="$odesc$o"
|
||||
done
|
||||
for o in "${os[@]}"; do
|
||||
if [[ "$o" == *:* ]]; then
|
||||
if [ "${2#\$}" != "$2" ]; then
|
||||
o=ARG
|
||||
else
|
||||
o="${2%%=*}"
|
||||
o="${o^^}"
|
||||
fi
|
||||
[ -n "$odesc" ] && odesc="$odesc "
|
||||
odesc="$odesc$o"
|
||||
fi
|
||||
break
|
||||
done
|
||||
array_add NUCORE_ARGS_HELP_OPTIONS "$odesc"
|
||||
[ -n "$3" ] && array_add NUCORE_ARGS_HELP_OPTIONS "$3"
|
||||
}
|
||||
|
||||
function: myargs_show_help ""
|
||||
function myargs_show_help() {
|
||||
local help="$MYNAME"
|
||||
[ -n "$NUCORE_ARGS_HELP_DESC" ] && help="$help: $NUCORE_ARGS_HELP_DESC"
|
||||
[ -n "$NUCORE_ARGS_HELP_USAGE" ] && help="$help
|
||||
|
||||
USAGE
|
||||
$NUCORE_ARGS_HELP_USAGE"
|
||||
[ ${#NUCORE_ARGS_HELP_OPTIONS[*]} -gt 0 ] && help="$help
|
||||
|
||||
OPTIONS"
|
||||
echo "$help"
|
||||
for help in "${NUCORE_ARGS_HELP_OPTIONS[@]}"; do
|
||||
echo "$help"
|
||||
done
|
||||
}
|
||||
|
||||
function: myargs_parse ""
|
||||
function myargs_parse() {
|
||||
[ -z "$NUCORE_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local NUCORE_ARGS_SET_X=1; }
|
||||
local r=0
|
||||
if ! parse_opts "${PRETTYOPTS[@]}" "${args[@]}" @ args -- "$@"; then
|
||||
edie "$args"
|
||||
r=$?
|
||||
fi
|
||||
[ -n "$NUCORE_ARGS_SET_X" ] && set -x; return $r
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.arr "Fonctions de base: gestion des variables tableaux"
|
||||
require: base.core base.str
|
||||
|
||||
function: array_count "retourner le nombre d'éléments du tableau \$1"
|
||||
function array_count() {
|
||||
eval "echo \${#$1[*]}"
|
||||
}
|
||||
|
||||
function: array_isempty "tester si le tableau \$1 est vide"
|
||||
function array_isempty() {
|
||||
eval "[ \${#$1[*]} -eq 0 ]"
|
||||
}
|
||||
|
||||
function: array_new "créer un tableau vide dans la variable \$1"
|
||||
function array_new() {
|
||||
eval "$1=()"
|
||||
}
|
||||
|
||||
function: array_copy "copier le contenu du tableau \$2 dans le tableau \$1"
|
||||
function array_copy() {
|
||||
eval "$1=(\"\${$2[@]}\")"
|
||||
}
|
||||
|
||||
function: array_add "ajouter les valeurs \$2..@ à la fin du tableau \$1"
|
||||
function array_add() {
|
||||
local __aa_a="$1"; shift
|
||||
eval "$__aa_a+=(\"\$@\")"
|
||||
}
|
||||
|
||||
function: array_ins "insérer les valeurs \$2..@ au début du tableau \$1"
|
||||
function array_ins() {
|
||||
local __aa_a="$1"; shift
|
||||
eval "$__aa_a=(\"\$@\" \"\${$__aa_a[@]}\")"
|
||||
}
|
||||
|
||||
function: array_del "supprimer *les* valeurs \$2 du tableau \$1"
|
||||
function array_del() {
|
||||
local __ad_v
|
||||
local -a __ad_vs
|
||||
eval '
|
||||
for __ad_v in "${'"$1"'[@]}"; do
|
||||
if [ "$__ad_v" != "$2" ]; then
|
||||
__ad_vs=("${__ad_vs[@]}" "$__ad_v")
|
||||
fi
|
||||
done'
|
||||
array_copy "$1" __ad_vs
|
||||
}
|
||||
|
||||
function: array_addu "ajouter la valeur \$2 au tableau \$1, si la valeur n'y est pas déjà
|
||||
|
||||
Retourner vrai si la valeur a été ajoutée"
|
||||
function array_addu() {
|
||||
local __as_v
|
||||
eval '
|
||||
for __as_v in "${'"$1"'[@]}"; do
|
||||
[ "$__as_v" == "$2" ] && return 1
|
||||
done'
|
||||
array_add "$1" "$2"
|
||||
return 0
|
||||
}
|
||||
|
||||
function: array_insu "insérer la valeur \$2 au début du tableau tableau \$1, si la valeur n'y est pas déjà
|
||||
|
||||
Retourner vrai si la valeur a été ajoutée."
|
||||
function array_insu() {
|
||||
local __as_v
|
||||
eval '
|
||||
for __as_v in "${'"$1"'[@]}"; do
|
||||
[ "$__as_v" == "$2" ] && return 1
|
||||
done'
|
||||
array_ins "$1" "$2"
|
||||
return 0
|
||||
}
|
||||
|
||||
function: array_fillrange "Initialiser le tableau \$1 avec les nombres de \$2(=1) à \$3(=10) avec un step de \$4(=1)"
|
||||
function array_fillrange() {
|
||||
local -a __af_vs
|
||||
local __af_i="${2:-1}" __af_to="${3:-10}" __af_step="${4:-1}"
|
||||
while [ "$__af_i" -le "$__af_to" ]; do
|
||||
__af_vs=("${__af_vs[@]}" "$__af_i")
|
||||
__af_i=$(($__af_i + $__af_step))
|
||||
done
|
||||
array_copy "$1" __af_vs
|
||||
}
|
||||
|
||||
function: array_eq "tester l'égalité des tableaux \$1 et \$2"
|
||||
function array_eq() {
|
||||
local -a __ae_a1 __ae_a2
|
||||
array_copy __ae_a1 "$1"
|
||||
array_copy __ae_a2 "$2"
|
||||
[ ${#__ae_a1[*]} -eq ${#__ae_a2[*]} ] || return 1
|
||||
local __ae_v __ae_i=0
|
||||
for __ae_v in "${__ae_a1[@]}"; do
|
||||
[ "$__ae_v" == "${__ae_a2[$__ae_i]}" ] || return 1
|
||||
__ae_i=$(($__ae_i + 1))
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
function: array_contains "tester si le tableau \$1 contient la valeur \$2"
|
||||
function array_contains() {
|
||||
local __ac_v
|
||||
eval '
|
||||
for __ac_v in "${'"$1"'[@]}"; do
|
||||
[ "$__ac_v" == "$2" ] && return 0
|
||||
done'
|
||||
return 1
|
||||
}
|
||||
|
||||
function: array_icontains "tester si le tableau \$1 contient la valeur \$2, sans tenir compte de la casse"
|
||||
function array_icontains() {
|
||||
local __ac_v
|
||||
eval '
|
||||
for __ac_v in "${'"$1"'[@]}"; do
|
||||
[ "${__ac_v,,} == "${2,,}" ] && return 0
|
||||
done'
|
||||
return 1
|
||||
}
|
||||
|
||||
function: array_find "si le tableau \$1 contient la valeur \$2, afficher l'index de la valeur. Si le tableau \$3 est spécifié, afficher la valeur à l'index dans ce tableau"
|
||||
function array_find() {
|
||||
local __af_i __af_v
|
||||
__af_i=0
|
||||
eval '
|
||||
for __af_v in "${'"$1"'[@]}"; do
|
||||
if [ "$__af_v" == "$2" ]; then
|
||||
if [ -n "$3" ]; then
|
||||
recho "${'"$3"'[$__af_i]}"
|
||||
else
|
||||
echo "$__af_i"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
__af_i=$(($__af_i + 1))
|
||||
done'
|
||||
return 1
|
||||
}
|
||||
|
||||
function: array_reverse "Inverser l'ordre des élément du tableau \$1"
|
||||
function array_reverse() {
|
||||
local -a __ar_vs
|
||||
local __ar_v
|
||||
array_copy __ar_vs "$1"
|
||||
array_new "$1"
|
||||
for __ar_v in "${__ar_vs[@]}"; do
|
||||
array_ins "$1" "$__ar_v"
|
||||
done
|
||||
}
|
||||
|
||||
function: array_replace "dans le tableau \$1, remplacer toutes les occurences de \$2 par \$3..*"
|
||||
function array_replace() {
|
||||
local __ar_sn="$1"; shift
|
||||
local __ar_f="$1"; shift
|
||||
local -a __ar_s __ar_d
|
||||
local __ar_v
|
||||
array_copy __ar_s "$__ar_sn"
|
||||
for __ar_v in "${__ar_s[@]}"; do
|
||||
if [ "$__ar_v" == "$__ar_f" ]; then
|
||||
__ar_d=("${__ar_d[@]}" "$@")
|
||||
else
|
||||
__ar_d=("${__ar_d[@]}" "$__ar_v")
|
||||
fi
|
||||
done
|
||||
array_copy "$__ar_sn" __ar_d
|
||||
}
|
||||
|
||||
function: array_each "Pour chacune des valeurs ITEM du tableau \$1, appeler la fonction \$2 avec les arguments (\$3..@ ITEM)"
|
||||
function array_each() {
|
||||
local __ae_v
|
||||
local -a __ae_a
|
||||
array_copy __ae_a "$1"; shift
|
||||
for __ae_v in "${__ae_a[@]}"; do
|
||||
"$@" "$__ae_v"
|
||||
done
|
||||
}
|
||||
|
||||
function: array_map "Pour chacune des valeurs ITEM du tableau \$1, appeler la fonction \$2 avec les arguments (\$3..@ ITEM), et remplacer la valeur par le résultat de la fonction"
|
||||
function array_map() {
|
||||
local __am_v
|
||||
local -a __am_a __am_vs
|
||||
local __am_an="$1"; shift
|
||||
local __am_f="$1"; shift
|
||||
array_copy __am_a "$__am_an"
|
||||
for __am_v in "${__am_a[@]}"; do
|
||||
__am_vs=("${__am_vs[@]}" "$("$__am_f" "$@" "$__am_v")")
|
||||
done
|
||||
array_copy "$__am_an" __am_vs
|
||||
}
|
||||
|
||||
function: array_first "afficher la première valeur du tableau \$1"
|
||||
function array_first() {
|
||||
eval "recho \"\${$1[@]:0:1}\""
|
||||
}
|
||||
|
||||
function: array_last "afficher la dernière valeur du tableau \$1"
|
||||
function array_last() {
|
||||
eval "recho \"\${$1[@]: -1:1}\""
|
||||
}
|
||||
|
||||
function: array_copy_firsts "copier toutes les valeurs du tableau \$2(=\$1) dans le tableau \$1, excepté la dernière"
|
||||
function array_copy_firsts() {
|
||||
eval "$1=(\"\${${2:-$1}[@]:0:\$((\${#${2:-$1}[@]}-1))}\")"
|
||||
}
|
||||
|
||||
function: array_copy_lasts "copier toutes les valeurs du tableau \$2(=\$1) dans le tableau \$1, excepté la première"
|
||||
function array_copy_lasts() {
|
||||
eval "$1=(\"\${${2:-$1}[@]:1}\")"
|
||||
}
|
||||
|
||||
function: array_extend "ajouter le contenu du tableau \$2 au tableau \$1"
|
||||
function array_extend() {
|
||||
eval "$1=(\"\${$1[@]}\" \"\${$2[@]}\")"
|
||||
}
|
||||
|
||||
function: array_extendu "ajouter chacune des valeurs du tableau \$2 au tableau \$1, si ces valeurs n'y sont pas déjà
|
||||
|
||||
Retourner vrai si au moins une valeur a été ajoutée"
|
||||
function array_extendu() {
|
||||
local __ae_v __ae_s=1
|
||||
eval '
|
||||
for __ae_v in "${'"$2"'[@]}"; do
|
||||
array_addu "$1" "$__ae_v" && __ae_s=0
|
||||
done'
|
||||
return "$__ae_s"
|
||||
}
|
||||
|
||||
function: array_extend_firsts "ajouter toutes les valeurs du tableau \$2 dans le tableau \$1, excepté la dernière"
|
||||
function array_extend_firsts() {
|
||||
eval "$1=(\"\${$1[@]}\" \"\${$2[@]:0:\$((\${#$2[@]}-1))}\")"
|
||||
}
|
||||
|
||||
function: array_extend_lasts "ajouter toutes les valeurs du tableau \$2 dans le tableau \$1, excepté la première"
|
||||
function array_extend_lasts() {
|
||||
eval "$1=(\"\${$1[@]}\" \"\${$2[@]:1}\")"
|
||||
}
|
||||
|
||||
function: array_xsplit "créer le tableau \$1 avec chaque élément de \$2 (un ensemble d'éléments séparés par \$3, qui vaut ':' par défaut)"
|
||||
function array_xsplit() {
|
||||
eval "$1=($(recho_ "$2" | lawk -v RS="${3:-:}" '
|
||||
{
|
||||
gsub(/'\''/, "'\'\\\\\'\''")
|
||||
print "'\''" $0 "'\''"
|
||||
}'))" #"
|
||||
}
|
||||
|
||||
function: array_xsplitc "variante de array_xsplit() où le séparateur est ',' par défaut"
|
||||
function array_xsplitc() {
|
||||
array_xsplit "$1" "$2" "${3:-,}"
|
||||
}
|
||||
|
||||
function: array_split "créer le tableau \$1 avec chaque élément de \$2 (un ensemble d'éléments séparés par \$3, qui vaut ':' par défaut)
|
||||
|
||||
Les éléments vides sont ignorés. par exemple \"a::b\" est équivalent à \"a:b\""
|
||||
function array_split() {
|
||||
eval "$1=($(recho_ "$2" | lawk -v RS="${3:-:}" '
|
||||
/^$/ { next }
|
||||
{
|
||||
gsub(/'\''/, "'\'\\\\\'\''")
|
||||
print "'\''" $0 "'\''"
|
||||
}'))" #"
|
||||
}
|
||||
|
||||
function: array_splitc "variante de array_split() où le séparateur est ',' par défaut"
|
||||
function array_splitc() {
|
||||
array_split "$1" "$2" "${3:-,}"
|
||||
}
|
||||
|
||||
function: array_xsplitl "créer le tableau \$1 avec chaque ligne de \$2"
|
||||
function array_xsplitl() {
|
||||
eval "$1=($(recho_ "$2" | strnl2lf | lawk '
|
||||
{
|
||||
gsub(/'\''/, "'\'\\\\\'\''")
|
||||
print "'\''" $0 "'\''"
|
||||
}'))" #"
|
||||
}
|
||||
|
||||
function: array_splitl "créer le tableau \$1 avec chaque ligne de \$2
|
||||
|
||||
Les lignes vides sont ignorés."
|
||||
function array_splitl() {
|
||||
eval "$1=($(recho_ "$2" | strnl2lf | lawk '
|
||||
/^$/ { next }
|
||||
{
|
||||
gsub(/'\''/, "'\'\\\\\'\''")
|
||||
print "'\''" $0 "'\''"
|
||||
}'))" #"
|
||||
}
|
||||
|
||||
function: array_join "afficher le contenu du tableau \$1 sous forme d'une liste de valeurs séparées par \$2 (qui vaut ':' par défaut)
|
||||
|
||||
* Si \$1==\"@\", alors les éléments du tableaux sont les arguments de la fonction à partir de \$3
|
||||
* Si \$1!=\"@\" et que le tableau est vide, afficher \$3
|
||||
* Si \$1!=\"@\", \$4 et \$5 sont des préfixes et suffixes à rajouter à chaque élément"
|
||||
function array_join() {
|
||||
local __aj_an __aj_l __aj_j __aj_s="${2:-:}" __aj_pf __aj_sf
|
||||
if [ "$1" == "@" ]; then
|
||||
__aj_an="\$@"
|
||||
shift; shift
|
||||
else
|
||||
__aj_an="\${$1[@]}"
|
||||
__aj_pf="$4"
|
||||
__aj_sf="$5"
|
||||
fi
|
||||
eval '
|
||||
for __aj_l in "'"$__aj_an"'"; do
|
||||
__aj_j="${__aj_j:+$__aj_j'"$__aj_s"'}$__aj_pf$__aj_l$__aj_sf"
|
||||
done'
|
||||
if [ -n "$__aj_j" ]; then
|
||||
recho "$__aj_j"
|
||||
elif [ "$__aj_an" != "\$@" -a -n "$3" ]; then
|
||||
recho "$3"
|
||||
fi
|
||||
}
|
||||
|
||||
function: array_joinc "afficher les éléments du tableau \$1 séparés par ','"
|
||||
function array_joinc() {
|
||||
array_join "$1" , "$2" "$3" "$4"
|
||||
}
|
||||
|
||||
function: array_joinl "afficher les éléments du tableau \$1 à raison d'un élément par ligne"
|
||||
function array_joinl() {
|
||||
array_join "$1" "
|
||||
" "$2" "$3" "$4"
|
||||
}
|
||||
|
||||
function: array_mapjoin "map le tableau \$1 avec la fonction \$2, puis afficher le résultat en séparant chaque élément par \$3
|
||||
|
||||
Les arguments et la sémantique sont les mêmes que pour array_join() en
|
||||
tenant compte de l'argument supplémentaire \$2 qui est la fonction pour
|
||||
array_map() (les autres arguments sont décalés en conséquence)"
|
||||
function array_mapjoin() {
|
||||
local __amj_src="$1" __amj_func="$2" __amj_sep="$3"
|
||||
shift; shift; shift
|
||||
if [ "$__amj_src" == "@" ]; then
|
||||
local -a __amj_tmpsrc
|
||||
__amj_tmpsrc=("$@")
|
||||
__amj_src=__amj_tmpsrc
|
||||
set --
|
||||
fi
|
||||
local -a __amj_tmp
|
||||
array_copy __amj_tmp "$__amj_src"
|
||||
array_map __amj_tmp "$__amj_func"
|
||||
array_join __amj_tmp "$__amj_sep" "$@"
|
||||
}
|
||||
|
||||
function: array_fix_paths "Corriger les valeurs du tableau \$1. Les valeurs contenant le séparateur \$2(=':') sont séparées en plusieurs valeurs.
|
||||
|
||||
Par exemple avec le tableau input=(a b:c), le résultat est input=(a b c)"
|
||||
function array_fix_paths() {
|
||||
local __afp_an="$1" __afp_s="${2:-:}"
|
||||
local -a __afp_vs
|
||||
local __afp_v
|
||||
array_copy __afp_vs "$__afp_an"
|
||||
array_new "$__afp_an"
|
||||
for __afp_v in "${__afp_vs[@]}"; do
|
||||
array_split __afp_v "$__afp_v" "$__afp_s"
|
||||
array_extend "$__afp_an" __afp_v
|
||||
done
|
||||
}
|
|
@ -0,0 +1,458 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.core "Fonctions de base: fondement"
|
||||
|
||||
function: echo_ "afficher la valeur \$* sans passer à la ligne"
|
||||
function echo_() { echo -n "$*"; }
|
||||
|
||||
function: recho "afficher une valeur brute.
|
||||
|
||||
contrairement à la commande echo, ne reconnaitre aucune option (i.e. -e, -E, -n
|
||||
ne sont pas signifiants)"
|
||||
function recho() {
|
||||
if [[ "${1:0:2}" == -[eEn] ]]; then
|
||||
local first="${1:1}"; shift
|
||||
echo -n -
|
||||
echo "$first" "$@"
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function: recho_ "afficher une valeur brute, sans passer à la ligne.
|
||||
|
||||
contrairement à la commande echo, ne reconnaitre aucune option (i.e. -e, -E, -n
|
||||
ne sont pas signifiants)"
|
||||
function recho_() {
|
||||
if [[ "${1:0:2}" == -[eEn] ]]; then
|
||||
local first="${1:1}"; shift
|
||||
echo -n -
|
||||
echo -n "$first" "$@"
|
||||
else
|
||||
echo -n "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function: _qval "Dans la chaine \$*, remplacer:
|
||||
~~~
|
||||
\\ par \\\\
|
||||
\" par \\\"
|
||||
\$ par \\\$
|
||||
\` par \\\`
|
||||
~~~
|
||||
|
||||
Cela permet de quoter une chaine à mettre entre guillements.
|
||||
|
||||
note: la protection de ! n'est pas effectuée, parce que le comportement du shell
|
||||
est incohérent entre le shell interactif et les scripts. Pour une version plus
|
||||
robuste, il est nécessaire d'utiliser un programme externe tel que sed ou awk"
|
||||
function _qval() {
|
||||
local s="$*"
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\"/\\\"}"
|
||||
s="${s//\$/\\\$}"
|
||||
s="${s//\`/\\\`}"
|
||||
recho_ "$s"
|
||||
}
|
||||
|
||||
function: should_quote "Tester si la chaine \$* doit être mise entre quotes"
|
||||
function should_quote() {
|
||||
# pour optimiser, toujours mettre entre quotes si plusieurs arguments sont
|
||||
# spécifiés ou si on spécifie une chaine vide ou de plus de 80 caractères
|
||||
[ $# -eq 0 -o $# -gt 1 -o ${#1} -eq 0 -o ${#1} -gt 80 ] && return 0
|
||||
# sinon, tester si la chaine contient des caractères spéciaux
|
||||
local s="$*"
|
||||
s="${s//[a-zA-Z0-9]/}"
|
||||
s="${s//,/}"
|
||||
s="${s//./}"
|
||||
s="${s//+/}"
|
||||
s="${s//\//}"
|
||||
s="${s//-/}"
|
||||
s="${s//_/}"
|
||||
s="${s//=/}"
|
||||
[ -n "$s" ]
|
||||
}
|
||||
|
||||
function: qval "Afficher la chaine \$* quotée avec \""
|
||||
function qval() {
|
||||
echo -n \"
|
||||
_qval "$@"
|
||||
echo \"
|
||||
}
|
||||
|
||||
function: qvalm "Afficher la chaine \$* quotée si nécessaire avec \""
|
||||
function qvalm() {
|
||||
if should_quote "$@"; then
|
||||
echo -n \"
|
||||
_qval "$@"
|
||||
echo \"
|
||||
else
|
||||
recho "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function: qvalr "Afficher la chaine \$* quotée si nécessaire avec \", sauf si elle est vide"
|
||||
function qvalr() {
|
||||
if [ -z "$*" ]; then
|
||||
:
|
||||
elif should_quote "$@"; then
|
||||
echo -n \"
|
||||
_qval "$@"
|
||||
echo \"
|
||||
else
|
||||
recho "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function: qvals "Afficher chaque argument de cette fonction quotée le cas échéant avec \", chaque valeur étant séparée par un espace"
|
||||
function qvals() {
|
||||
local arg first=1
|
||||
for arg in "$@"; do
|
||||
[ -z "$first" ] && echo -n " "
|
||||
if should_quote "$arg"; then
|
||||
echo -n \"
|
||||
_qval "$arg"
|
||||
echo -n \"
|
||||
else
|
||||
recho_ "$arg"
|
||||
fi
|
||||
first=
|
||||
done
|
||||
[ -z "$first" ] && echo
|
||||
}
|
||||
|
||||
function: qwc "Dans la chaine \$*, remplacer:
|
||||
~~~
|
||||
\\ par \\\\
|
||||
\" par \\\"
|
||||
\$ par \\\$
|
||||
\` par \\\`
|
||||
~~~
|
||||
puis quoter la chaine avec \", sauf les wildcards *, ? et [class]
|
||||
|
||||
Cela permet de quoter une chaine permettant de glober des fichiers, e.g
|
||||
~~~
|
||||
eval \"ls \$(qwc \"\$value\")\"
|
||||
~~~
|
||||
|
||||
note: la protection de ! n'est pas effectuée, parce que le comportement du shell
|
||||
est incohérent entre le shell interactif et les scripts. Pour une version plus
|
||||
robuste, il est nécessaire d'utiliser un programme externe tel que sed ou awk"
|
||||
function qwc() {
|
||||
local s="$*"
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\"/\\\"}"
|
||||
s="${s//\$/\\\$}"
|
||||
s="${s//\`/\\\`}"
|
||||
local r a b c
|
||||
while [ -n "$s" ]; do
|
||||
a=; b=; c=
|
||||
a=; [[ "$s" == *\** ]] && { a="${s%%\**}"; a=${#a}; }
|
||||
b=; [[ "$s" == *\?* ]] && { b="${s%%\?*}"; b=${#b}; }
|
||||
c=; [[ "$s" == *\[* ]] && { c="${s%%\[*}"; c=${#c}; }
|
||||
if [ -z "$a" -a -z "$b" -a -z "$c" ]; then
|
||||
r="$r\"$s\""
|
||||
break
|
||||
fi
|
||||
if [ -n "$a" ]; then
|
||||
[ -n "$b" ] && [ $a -lt $b ] && b=
|
||||
[ -n "$c" ] && [ $a -lt $c ] && c=
|
||||
fi
|
||||
if [ -n "$b" ]; then
|
||||
[ -n "$a" ] && [ $b -lt $a ] && a=
|
||||
[ -n "$c" ] && [ $b -lt $c ] && c=
|
||||
fi
|
||||
if [ -n "$c" ]; then
|
||||
[ -n "$a" ] && [ $c -lt $a ] && a=
|
||||
[ -n "$b" ] && [ $c -lt $b ] && b=
|
||||
fi
|
||||
if [ -n "$a" ]; then # PREFIX*
|
||||
a="${s%%\**}"
|
||||
s="${s#*\*}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r*"
|
||||
elif [ -n "$b" ]; then # PREFIX?
|
||||
a="${s%%\?*}"
|
||||
s="${s#*\?}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r?"
|
||||
elif [ -n "$c" ]; then # PREFIX[class]
|
||||
a="${s%%\[*}"
|
||||
b="${s#*\[}"; b="${b%%\]*}"
|
||||
s="${s:$((${#a} + ${#b} + 2))}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r[$b]"
|
||||
fi
|
||||
done
|
||||
recho_ "$r"
|
||||
}
|
||||
|
||||
function: qlines "Traiter chaque ligne de l'entrée standard pour en faire des chaines quotées avec '"
|
||||
function qlines() {
|
||||
sed "s/'/'\\\\''/g; s/.*/'&'/g"
|
||||
}
|
||||
|
||||
function: setv "initialiser la variable \$1 avec la valeur \$2..*
|
||||
|
||||
note: en principe, la syntaxe est 'setv var values...'. cependant, la syntaxe 'setv var=values...' est supportée aussi"
|
||||
function setv() {
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
fi
|
||||
eval "$s__var=\"\$*\""
|
||||
}
|
||||
|
||||
function: _setv "Comme la fonction setv() mais ne supporte que la syntaxe '_setv var values...'
|
||||
|
||||
Cette fonction est légèrement plus rapide que setv()"
|
||||
function _setv() {
|
||||
local s__var="$1"; shift
|
||||
eval "$s__var=\"\$*\""
|
||||
}
|
||||
|
||||
function: echo_setv "Afficher la commande qui serait lancée par setv \"\$@\""
|
||||
function echo_setv() {
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
fi
|
||||
echo "$s__var=$(qvalr "$*")"
|
||||
}
|
||||
|
||||
function: echo_setv2 "Afficher la commande qui recrée la variable \$1.
|
||||
|
||||
Equivalent à
|
||||
~~~
|
||||
echo_setv \"\$1=\${!1}\"
|
||||
~~~
|
||||
|
||||
Si d'autres arguments que le nom de la variable sont spécifiés, cette fonction
|
||||
se comporte comme echo_setv()"
|
||||
function echo_setv2() {
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
fi
|
||||
if [ $# -eq 0 ]; then
|
||||
echo_setv "$s__var" "${!s__var}"
|
||||
else
|
||||
echo_setv "$s__var" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
function: seta "initialiser le tableau \$1 avec les valeurs \$2..@
|
||||
|
||||
note: en principe, la syntaxe est 'seta array values...'. cependant, la syntaxe
|
||||
'seta array=values...' est supportée aussi"
|
||||
function seta() {
|
||||
local s__array="$1"; shift
|
||||
if [[ "$s__array" == *=* ]]; then
|
||||
set -- "${s__array#*=}" "$@"
|
||||
s__array="${s__array%%=*}"
|
||||
fi
|
||||
eval "$s__array=(\"\$@\")"
|
||||
}
|
||||
|
||||
function: _seta "Comme la fonction seta() mais ne supporte que la syntaxe '_seta array values...'
|
||||
|
||||
Cette fonction est légèrement plus rapide que seta()"
|
||||
function _seta() {
|
||||
local s__array="$1"; shift
|
||||
eval "$s__array=(\"\$@\")"
|
||||
}
|
||||
|
||||
function: echo_seta "Afficher la commande qui serait lancée par seta \"\$@\""
|
||||
function echo_seta() {
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
fi
|
||||
echo "$s__var=($(qvals "$@"))"
|
||||
}
|
||||
|
||||
function: echo_seta2 "Afficher la commande qui recrée le tableau \$1
|
||||
|
||||
Si d'autres arguments que le nom de tableau sont spécifiés, cette fonction se
|
||||
comporte comme echo_seta()"
|
||||
function echo_seta2() {
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
elif [ $# -eq 0 ]; then
|
||||
eval "set -- \"\${$s__var[@]}\""
|
||||
fi
|
||||
echo "$s__var=($(qvals "$@"))"
|
||||
}
|
||||
|
||||
function: setx "Initialiser une variable avec le résultat d'une commande
|
||||
|
||||
* syntaxe 1: initialiser la variable \$1 avec le résultat de la commande \"\$2..@\"
|
||||
~~~
|
||||
setx var cmd
|
||||
~~~
|
||||
note: en principe, la syntaxe est 'setx var cmd args...'. cependant, la syntaxe
|
||||
'setx var=cmd args...' est supportée aussi
|
||||
|
||||
* syntaxe 2: initialiser le tableau \$1 avec le résultat de la commande
|
||||
\"\$2..@\", chaque ligne du résultat étant un élément du tableau
|
||||
~~~
|
||||
setx -a array cmd
|
||||
~~~
|
||||
note: en principe, la syntaxe est 'setx -a array cmd args...'. cependant, la
|
||||
syntaxe 'setx -a array=cmd args...' est supportée aussi"
|
||||
function setx() {
|
||||
if [ "$1" == -a ]; then
|
||||
shift
|
||||
local s__array="$1"; shift
|
||||
if [[ "$s__array" == *=* ]]; then
|
||||
set -- "${s__array#*=}" "$@"
|
||||
s__array="${s__array%%=*}"
|
||||
fi
|
||||
eval "$s__array=($("$@" | qlines))"
|
||||
else
|
||||
local s__var="$1"; shift
|
||||
if [[ "$s__var" == *=* ]]; then
|
||||
set -- "${s__var#*=}" "$@"
|
||||
s__var="${s__var%%=*}"
|
||||
fi
|
||||
eval "$s__var="'"$("$@")"'
|
||||
fi
|
||||
}
|
||||
|
||||
function: _setvx "Comme la fonction setx() mais ne supporte que l'initialisation d'une variable scalaire avec la syntaxe '_setvx var cmd args...' pour gagner (un peu) en rapidité d'exécution."
|
||||
function _setvx() {
|
||||
local s__var="$1"; shift
|
||||
eval "$s__var="'"$("$@")"'
|
||||
}
|
||||
|
||||
function: _setax "Comme la fonction setx() mais ne supporte que l'initialisation d'un tableau avec la syntaxe '_setax array cmd args...' pour gagner (un peu) en rapidité d'exécution."
|
||||
function _setax() {
|
||||
local s__array="$1"; shift
|
||||
eval "$s__array=($("$@" | qlines))"
|
||||
}
|
||||
|
||||
function: is_defined "tester si la variable \$1 est définie"
|
||||
function is_defined() {
|
||||
[ -n "$(declare -p "$1" 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
function: is_array "tester si la variable \$1 est un tableau"
|
||||
function is_array() {
|
||||
[[ "$(declare -p "$1" 2>/dev/null)" =~ declare\ -[^\ ]*a[^\ ]*\ ]]
|
||||
}
|
||||
|
||||
function: array_local "afficher les commandes pour faire une copie dans la variable locale \$1 du tableau \$2"
|
||||
function array_local() {
|
||||
if [ "$1" == "$2" ]; then
|
||||
declare -p "$1" 2>/dev/null || echo "local -a $1"
|
||||
else
|
||||
echo "local -a $1; $1=(\"\${$2[@]}\")"
|
||||
fi
|
||||
}
|
||||
|
||||
function: upvar "Implémentation de upvar() de http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
||||
|
||||
USAGE
|
||||
~~~
|
||||
local varname && upvar varname values...
|
||||
~~~
|
||||
* @param varname Variable name to assign value to
|
||||
* @param values Value(s) to assign. If multiple values (> 1), an array is
|
||||
assigned, otherwise a single value is assigned."
|
||||
function upvar() {
|
||||
if unset -v "$1"; then
|
||||
if [ $# -lt 2 ]; then
|
||||
eval "$1=\"\$2\""
|
||||
else
|
||||
eval "$1=(\"\${@:2}\")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function: array_upvar "Comme upvar() mais force la création d'un tableau, même s'il y a que 0 ou 1 argument"
|
||||
function array_upvar() {
|
||||
unset -v "$1" && eval "$1=(\"\${@:2}\")"
|
||||
}
|
||||
|
||||
function: upvars "Implémentation modifiée de upvars() de http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
||||
|
||||
Par rapport à l'original, il n'est plus nécessaire de préfixer une variable
|
||||
scalaire avec -v, et -a peut être spécifié sans argument.
|
||||
|
||||
USAGE
|
||||
~~~
|
||||
local varnames... && upvars [varname value | -aN varname values...]...
|
||||
~~~
|
||||
* @param -a assigns remaining values to varname as array
|
||||
* @param -aN assigns next N values to varname as array. Returns 1 if wrong
|
||||
number of options occurs"
|
||||
function upvars() {
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-a)
|
||||
unset -v "$2" && eval "$2=(\"\${@:3}\")"
|
||||
break
|
||||
;;
|
||||
-a*)
|
||||
unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
|
||||
shift $((${1#-a} + 2)) || return 1
|
||||
;;
|
||||
*)
|
||||
unset -v "$1" && eval "$1=\"\$2\""
|
||||
shift; shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
function: set_debug "Passer en mode DEBUG"
|
||||
function set_debug() {
|
||||
export NUCORE_DEBUG=1
|
||||
}
|
||||
|
||||
function: is_debug "Tester si on est en mode DEBUG"
|
||||
function is_debug() {
|
||||
[ -n "$NUCORE_DEBUG" ]
|
||||
}
|
||||
|
||||
function: lawk "Lancer GNUawk avec la librairie 'base'"
|
||||
function lawk() {
|
||||
gawk -i base.awk "$@"
|
||||
}
|
||||
|
||||
function: cawk "Lancer GNUawk avec LANG=C et la librairie 'base'
|
||||
|
||||
Le fait de forcer la valeur de LANG permet d'éviter les problèmes avec la locale"
|
||||
function cawk() {
|
||||
LANG=C gawk -i base.awk "$@"
|
||||
}
|
||||
|
||||
function: lsort "Lancer sort avec support de la locale courante"
|
||||
function: csort "Lancer sort avec LANG=C pour désactiver le support de la locale
|
||||
|
||||
Avec LANG!=C, sort utilise les règles de la locale pour le tri, et par
|
||||
exemple, avec LANG=fr_FR.UTF-8, la locale indique que les ponctuations doivent
|
||||
être ignorées."
|
||||
function lsort() { sort "$@"; }
|
||||
function csort() { LANG=C sort "$@"; }
|
||||
|
||||
function: lgrep "Lancer grep avec support de la locale courante"
|
||||
function: cgrep "Lancer grep avec LANG=C pour désactiver le support de la locale"
|
||||
function lgrep() { grep "$@"; }
|
||||
function cgrep() { LANG=C grep "$@"; }
|
||||
|
||||
function: lsed "Lancer sed avec support de la locale courante"
|
||||
function: csed "Lancer sed avec LANG=C pour désactiver le support de la locale"
|
||||
function lsed() { sed "$@"; }
|
||||
function csed() { LANG=C sed "$@"; }
|
||||
|
||||
function: ldiff "Lancer diff avec support de la locale courante"
|
||||
function: cdiff "Lancer diff avec LANG=C pour désactiver le support de la locale"
|
||||
function ldiff() { diff "$@"; }
|
||||
function cdiff() { LANG=C diff "$@"; }
|
|
@ -0,0 +1,468 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.eval "Fonctions de base: évaluation d'expressions"
|
||||
require: base.str base.arr
|
||||
|
||||
################################################################################
|
||||
# Chaines
|
||||
|
||||
function: evals "Appliquer à une chaine de caractères une suite de traitements, e.g:
|
||||
~~~
|
||||
evals var deref +suffix
|
||||
~~~
|
||||
est équivalent à
|
||||
~~~
|
||||
echo \"\${var}suffix\"
|
||||
~~~
|
||||
|
||||
En commençant avec la valeur initiale \$1, les arguments \$2..* sont des
|
||||
opérations à appliquer dans l'ordre.
|
||||
|
||||
Les opérations suivantes considèrent que la valeur courante est un nom de
|
||||
variable:
|
||||
~~~
|
||||
:- := :? :+ deref dcount
|
||||
~~~
|
||||
|
||||
Toutes les autres opérations travaillent directement avec la valeur
|
||||
courante. Les opérations suivantes appliquent une transformation:
|
||||
~~~
|
||||
# % / : ^ , +# -# +% -% + - mid repl
|
||||
~~~
|
||||
IMPORTANT: aucune de ces fonctions ne met en échappement les valeur des
|
||||
patterns. Ainsi, si un pattern contient des caractères interdits comme \\ ou \$,
|
||||
il faut d'abord le traiter avec _qval()
|
||||
|
||||
Les opérations suivantes font un test sur la valeur et retournent immédiatement:
|
||||
~~~
|
||||
= == != < > -eq -ne -lt -le -gt -ge -n -z
|
||||
~~~
|
||||
|
||||
La syntaxe des opérateurs standards de bash est reprise autant que possible, i.e
|
||||
si on a l'habitude d'écrire ${varOP} en bash, alors la syntaxe à utiliser à
|
||||
priori est 'evals var OP' ou 'evals var deref OP' suivant les
|
||||
opérateurs.
|
||||
|
||||
Autres opérateurs:
|
||||
~~~
|
||||
deref indirection
|
||||
dcount nombre d'éléments du tableau
|
||||
+#STR ajouter un préfixe
|
||||
-#STR supprimer un préfixe
|
||||
+%STR ou +STR ajouter un suffixe
|
||||
-%STR ou -STR supprimer un suffixe
|
||||
mid RANGE traiter la chaine avec strmid()
|
||||
repl FROM TO traiter la chaine avec strrepl()
|
||||
~~~
|
||||
|
||||
Tout autre opérateur est traité comme un appel à une fonction qui prend un seul
|
||||
argument, la valeur courante, et qui affiche le résultat."
|
||||
function evals() {
|
||||
local -a es__tmp
|
||||
local es__value="$1"; shift
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
# l'argument est le nom de la variable
|
||||
:-*|:=*|:\?*|:+*) eval 'es__value="${'"${es__value}$1"'}"';;
|
||||
d|deref) es__value="${!es__value}";;
|
||||
dc|dcount|ds|dsize)
|
||||
es__value="${es__value}[@]"
|
||||
es__tmp=("${!es__value}")
|
||||
es__value="${#es__tmp[@]}"
|
||||
;;
|
||||
# l'argument est la valeur de la variable
|
||||
\#*|%*|/*|:*|^*|,*) eval 'es__value="${es__value'"$1"'}"';;
|
||||
l|length) es__value="${#es__value}";;
|
||||
=|==|!=|\<|\>|-eq|-ne|-lt|-le|-gt|-ge)
|
||||
es__tmp=(\[ "$es__value" "$@" ]); "${es__tmp[@]}"; return $?;;
|
||||
-n|-z) es__tmp=(\[ "$1" "$es__value" ]); "${es__tmp[@]}"; return $?;;
|
||||
+#*) eval 'es__value="'"${1#+#}"'$es__value"';;
|
||||
-#*) eval 'es__value="${es__value'"${1#-}"'}"';;
|
||||
+%*) eval 'es__value="$es__value"'"${1#+%}";;
|
||||
+*) eval 'es__value="$es__value"'"${1#+}";;
|
||||
-%*) eval 'es__value="${es__value'"${1#-}"'}"';;
|
||||
-*) eval 'es__value="${es__value%'"${1#-}"'}"';;
|
||||
mid|strmid) eval 'es__value="$(strmid "$2" "$es__value")"'; shift;;
|
||||
repl|strrepl) eval 'es__value="$(strrepl "$2" "$3" "$es__value")"'; shift; shift;;
|
||||
*) es__value="$("$1" "$es__value")";;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo "$es__value"
|
||||
}
|
||||
|
||||
function: setxs "équivalent à setx \$1 evals \$2..@"
|
||||
function setxs() {
|
||||
local -a ss__args
|
||||
if [ "$1" == -a ]; then ss__args=(-a); shift; fi
|
||||
local ss__var="$1"; shift
|
||||
if [[ "$ss__var" == *=* ]]; then
|
||||
set -- "${ss__var#*=}" "$@"
|
||||
ss__var="${ss__var%%=*}"
|
||||
fi
|
||||
ss__args=("${ss__args[@]}" "$ss__var")
|
||||
setx "${ss__args[@]}" evals "$@"
|
||||
}
|
||||
|
||||
function: cmds "lancer une commande avec comme argument le résultat de evals
|
||||
|
||||
Par exemple, les deux commandes suivantes sont équivalentes:
|
||||
~~~
|
||||
cmds CMD ARGS... // EVALARGS
|
||||
CMD ARGS... \"\$(evals EVALARGS)\"
|
||||
~~~"
|
||||
function cmds() {
|
||||
local cs__arg
|
||||
local -a cs__cmd
|
||||
while [ $# -gt 0 ]; do
|
||||
cs__arg="$1"; shift
|
||||
[ "$cs__arg" == // ] && break
|
||||
cs__cmd=("${cs__cmd[@]}" "$cs__arg")
|
||||
done
|
||||
"${cs__cmd[@]}" "$(evals "$@")"
|
||||
}
|
||||
|
||||
function: evalm "construire une chaine en mixant chaines statiques et évaluations de commandes
|
||||
|
||||
Par exemple, les deux commandes suivantes sont équivalentes:
|
||||
~~~
|
||||
evalm //\"string\" cmd args // cmd args //\"string\"
|
||||
echo \"string\$(cmd args)\$(cmd args)string\"
|
||||
~~~"
|
||||
function evalm() {
|
||||
local em__val em__arg
|
||||
local -a em__cmd
|
||||
while [ $# -gt 0 ]; do
|
||||
em__arg="$1"
|
||||
if [ "${em__arg#//}" != "$em__arg" ]; then
|
||||
em__val="$em__val${em__arg#//}"
|
||||
shift
|
||||
continue
|
||||
fi
|
||||
em__cmd=()
|
||||
while [ $# -gt 0 ]; do
|
||||
em__arg="$1"
|
||||
[ "${em__arg#//}" != "$em__arg" ] && break
|
||||
shift
|
||||
if [ "${em__arg%//}" != "$em__arg" ]; then
|
||||
local em__tmp="${em__arg%//}"
|
||||
if [ -z "${em__tmp//\\/}" ]; then
|
||||
em__arg="${em__arg#\\}"
|
||||
em__cmd=("${em__cmd[@]}" "$em__arg")
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
em__cmd=("${em__cmd[@]}" "$em__arg")
|
||||
done
|
||||
[ ${#em__cmd[*]} -gt 0 ] && em__val="$em__val$("${em__cmd[@]}")"
|
||||
done
|
||||
echo "$em__val"
|
||||
}
|
||||
|
||||
function: setxm "équivalent à setx \$1 evalm \$2..@"
|
||||
function setxm() {
|
||||
local -a sm__args
|
||||
if [ "$1" == -a ]; then sm__args=(-a); shift; fi
|
||||
local sm__var="$1"; shift
|
||||
if [[ "$sm__var" == *=* ]]; then
|
||||
set -- "${sm__var#*=}" "$@"
|
||||
sm__var="${sm__var%%=*}"
|
||||
fi
|
||||
sm__args=("${sm__args[@]}" "$sm__var")
|
||||
setx "${sm__args[@]}" evalm "$@"
|
||||
}
|
||||
|
||||
function: cmdm "lancer une commande avec comme argument le résultat de evalm
|
||||
|
||||
Par exemple, les deux commandes suivantes sont équivalentes:
|
||||
~~~
|
||||
cmdm CMD ARGS... // EVALARGS
|
||||
CMD ARGS... \"\$(evalm EVALARGS)\"
|
||||
~~~"
|
||||
function cmdm() {
|
||||
local cm__arg
|
||||
local -a cm__cmd
|
||||
while [ $# -gt 0 ]; do
|
||||
cm__arg="$1"; shift
|
||||
[ "$cm__arg" == // ] && break
|
||||
cm__cmd=("${cm__cmd[@]}" "$cm__arg")
|
||||
done
|
||||
"${cm__cmd[@]}" "$(evalm "$@")"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Nombres
|
||||
|
||||
function: evali "Evaluer une expression numérique"
|
||||
function evali() {
|
||||
echo "$(($*))"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Tableaux
|
||||
|
||||
################################################################################
|
||||
# Composition
|
||||
|
||||
function: evalc "Implémenter une syntaxe lisible et naturelle permettant d'enchainer des traitements sur une valeur.
|
||||
|
||||
Par exemple, la commande
|
||||
~~~
|
||||
evalc cmd1... // cmd2... // cmd3...
|
||||
~~~
|
||||
est équivalente à la commande
|
||||
~~~
|
||||
cmd3... \"\$(cmd2... \"\$(cmd1...)\")\"
|
||||
~~~"
|
||||
function evalc() {
|
||||
local ec__arg ec__cmd ec__finalcmd
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
ec__arg="$1"; shift
|
||||
if [ "$ec__arg" == // ]; then
|
||||
if [ ${#ec__cmd} -gt 0 ]; then
|
||||
if [ ${#ec__finalcmd} -eq 0 ]; then ec__finalcmd="$ec__cmd"
|
||||
else ec__finalcmd="$ec__cmd \$($ec__finalcmd)"
|
||||
fi
|
||||
fi
|
||||
ec__cmd=
|
||||
continue
|
||||
elif [ "${ec__arg%//}" != "$ec__arg" ]; then
|
||||
local tmp="${ec__arg%//}"
|
||||
[ -z "${tmp//\\/}" ] && ec__arg="${ec__arg#\\}"
|
||||
fi
|
||||
ec__cmd="$ec__cmd \"$(_qval "$ec__arg")\""
|
||||
done
|
||||
if [ ${#ec__cmd} -gt 0 ]; then
|
||||
if [ ${#ec__finalcmd} -eq 0 ]; then ec__finalcmd="$ec__cmd"
|
||||
else ec__finalcmd="$ec__cmd \$($ec__finalcmd)"
|
||||
fi
|
||||
fi
|
||||
eval "$ec__finalcmd"
|
||||
}
|
||||
|
||||
function: setxc "équivalent à setx \$1 evalc \$2..@"
|
||||
function setxc() {
|
||||
local -a sx__args
|
||||
if [ "$1" == -a ]; then sx__args=(-a); shift; fi
|
||||
local sx__var="$1"; shift
|
||||
if [[ "$sx__var" == *=* ]]; then
|
||||
set -- "${sx__var#*=}" "$@"
|
||||
sx__var="${sx__var%%=*}"
|
||||
fi
|
||||
sx__args=("${sx__args[@]}" "$sx__var")
|
||||
setx "${sx__args[@]}" evalc "$@"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Chainage
|
||||
|
||||
function: evalp "Implémenter une syntaxe alternative permettant d'enchainer des traitements sur un flux de données.
|
||||
|
||||
Par exemple, la commande
|
||||
~~~
|
||||
evalp cmd1... // cmd2... // cmd3...
|
||||
~~~
|
||||
affiche le résultat de la commande
|
||||
~~~
|
||||
cmd1... | cmd2... | cmd3...
|
||||
~~~
|
||||
|
||||
Typiquement, cette fonction permet de faciliter la *construction* d'un
|
||||
enchainement de commandes par programme, ou de faciliter l'utilisation de la
|
||||
fonction setx() pour récupérer le résultat d'un enchainement. Dans les autres
|
||||
cas, il est plus simple et naturel d'écrire les enchainements avec la syntaxe de
|
||||
bash."
|
||||
function evalp() {
|
||||
local ep__arg ep__cmd
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
ep__arg="$1"; shift
|
||||
if [ "$ep__arg" == // ]; then
|
||||
ep__cmd="$ep__cmd |"
|
||||
continue
|
||||
elif [ "${ep__arg%//}" != "$ep__arg" ]; then
|
||||
local ep__tmp="${ep__arg%//}"
|
||||
if [ -z "${ep__tmp//\\/}" ]; then
|
||||
ep__arg="${ep__arg#\\}"
|
||||
fi
|
||||
fi
|
||||
ep__cmd="${ep__cmd:+$ep__cmd }\"$(_qval "$ep__arg")\""
|
||||
done
|
||||
eval "$ep__cmd"
|
||||
}
|
||||
|
||||
function: setxp "équivalent à setx \$1 evalp \$2..@"
|
||||
function setxp() {
|
||||
local -a sp__args
|
||||
if [ "$1" == -a ]; then sp__args=(-a); shift; fi
|
||||
local sp__var="$1"; shift
|
||||
if [[ "$sp__var" == *=* ]]; then
|
||||
set -- "${sp__var#*=}" "$@"
|
||||
sp__var="${sp__var%%=*}"
|
||||
fi
|
||||
sp__args=("${sp__args[@]}" "$sp__var")
|
||||
setx "${sp__args[@]}" evalp "$@"
|
||||
}
|
||||
|
||||
function: cmdp "lancer une commande avec comme argument le résultat de evalp
|
||||
|
||||
Par exemple, les deux commandes suivantes sont équivalentes:
|
||||
~~~
|
||||
cmdp CMD ARGS... // EVALARGS
|
||||
CMD ARGS... \"\$(evalp EVALARGS)\"
|
||||
~~~"
|
||||
function cmdp() {
|
||||
local cp__arg
|
||||
local -a cp__cmd
|
||||
while [ $# -gt 0 ]; do
|
||||
cp__arg="$1"; shift
|
||||
[ "$cp__arg" == // ] && break
|
||||
cp__cmd=("${cp__cmd[@]}" "$cp__arg")
|
||||
done
|
||||
"${cp__cmd[@]}" "$(evalp "$@")"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Générique
|
||||
|
||||
function: evalx ""
|
||||
function evalx() {
|
||||
:
|
||||
}
|
||||
|
||||
function: setxx "équivalent à setx \$1 evalx \$2..@"
|
||||
function setxx() {
|
||||
local -a sx__args
|
||||
if [ "$1" == -a ]; then sx__args=(-a); shift; fi
|
||||
local sx__var="$1"; shift
|
||||
if [[ "$sx__var" == *=* ]]; then
|
||||
set -- "${sx__var#*=}" "$@"
|
||||
sx__var="${sx__var%%=*}"
|
||||
fi
|
||||
sx__args=("${sx__args[@]}" "$sx__var")
|
||||
setx "${sx__args[@]}" evalx "$@"
|
||||
}
|
||||
|
||||
function: cmdx "lancer une commande avec comme argument le résultat de evalx
|
||||
|
||||
Par exemple, les deux commandes suivantes sont équivalentes:
|
||||
~~~
|
||||
cmdx CMD ARGS... // EVALARGS
|
||||
CMD ARGS... \"\$(evalx EVALARGS)\"
|
||||
~~~"
|
||||
function cmdx() {
|
||||
local cx__arg
|
||||
local -a cx__cmd
|
||||
while [ $# -gt 0 ]; do
|
||||
cx__arg="$1"; shift
|
||||
[ "$cx__arg" == // ] && break
|
||||
cx__cmd=("${cx__cmd[@]}" "$cx__arg")
|
||||
done
|
||||
"${cx__cmd[@]}" "$(evalx "$@")"
|
||||
}
|
||||
|
||||
function: cmdsplitf "\
|
||||
Cette fonction doit être appelée avec N arguments (avec N>1). Elle analyse et
|
||||
découpe l'argument \$N comme avec une ligne de commande du shell. Ensuite, elle
|
||||
appelle la fonction \$1 avec les arguments de \$2 à \${N-1}, suivi des arguments
|
||||
obtenus lors de l'analyse de l'argument \$N. Par exemple, la commande suivante:
|
||||
~~~
|
||||
strsplitf cmd arg1 \"long arg2\" \"arg3 'long arg4'\"
|
||||
~~~
|
||||
est équivalente à:
|
||||
~~~
|
||||
cmd arg1 \"long arg2\" arg3 \"long arg4\"
|
||||
~~~
|
||||
|
||||
Retourner le code 127 si la fonction à appeler n'est pas spécifiée. Retourner le
|
||||
code 126 si une erreur s'est produite lors de l'analyse de l'argument \$N"
|
||||
function cmdsplitf() {
|
||||
[ $# -gt 0 ] || return 127
|
||||
local func count
|
||||
func="$1"; shift
|
||||
count=$#
|
||||
if [ $count -gt 0 ]; then
|
||||
eval 'set -- "${@:1:$(($count-1))}" '"${!count}" || return 126
|
||||
fi
|
||||
"$func" "$@"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Tests
|
||||
|
||||
function: testx "Faire un test unaire avec la commande [ sur une valeur calculée avec evalx.
|
||||
|
||||
Utiliser la syntaxe 'testx op cmds...' e.g.
|
||||
~~~
|
||||
testx -z cmd1 // cmd2
|
||||
~~~"
|
||||
function testx() {
|
||||
local t__op="$1"; shift
|
||||
local t__val="$(evalx "$@")"
|
||||
[ $t__op "$t__val" ]
|
||||
}
|
||||
|
||||
function: test2x "Faire une test binaire avec la commande [ entre une valeur spécifiée et une valeur calculée avec evalx.
|
||||
|
||||
Utiliser la syntaxe 'test2x value op cmds...' e.g.
|
||||
~~~
|
||||
test2x value == cmd1 // cmd2
|
||||
~~~"
|
||||
function test2x() {
|
||||
local t__val1="$1"; shift
|
||||
local t__op="$1"; shift
|
||||
local t__val2="$(evalx "$@")"
|
||||
[ "$t__val1" $t__op "$t__val2" ]
|
||||
}
|
||||
|
||||
function: testrx "Faire une test binaire avec la commande [[ entre une valeur spécifiée et une valeur calculée avec evalx.
|
||||
|
||||
Utiliser la syntaxe 'testrx value op cmds...' e.g.
|
||||
~~~
|
||||
testrx value == cmd1 // cmd2
|
||||
~~~"
|
||||
function testrx() {
|
||||
local t__val1="$1"; shift
|
||||
local t__op="$1"; shift
|
||||
local t__val2="$(evalx "$@")"
|
||||
eval '[[ "$t__val1" '"$t__op"' "$t__val2" ]]'
|
||||
}
|
||||
|
||||
function: testp "Faire un test unaire avec la commande [ sur une valeur calculée avec evalp.
|
||||
|
||||
Utiliser la syntaxe 'testp op cmds...' e.g.
|
||||
~~~
|
||||
testp -z cmd1 // cmd2
|
||||
~~~"
|
||||
function testp() {
|
||||
local t__op="$1"; shift
|
||||
local t__val="$(evalp "$@")"
|
||||
[ $t__op "$t__val" ]
|
||||
}
|
||||
|
||||
function: test2p "Faire une test binaire avec la commande [ entre une valeur spécifiée et une valeur calculée avec evalp.
|
||||
|
||||
Utiliser la syntaxe 'test2p value op cmds...' e.g.
|
||||
~~~
|
||||
test2p value == cmd1 // cmd2
|
||||
~~~"
|
||||
function test2p() {
|
||||
local t__val1="$1"; shift
|
||||
local t__op="$1"; shift
|
||||
local t__val2="$(evalp "$@")"
|
||||
[ "$t__val1" $t__op "$t__val2" ]
|
||||
}
|
||||
|
||||
function: testrp "Faire une test binaire avec la commande [[ entre une valeur spécifiée et une valeur calculée avec evalp.
|
||||
|
||||
Utiliser la syntaxe 'testrp value op cmds...' e.g.
|
||||
~~~
|
||||
testrp value == cmd1 // cmd2
|
||||
~~~"
|
||||
function testrp() {
|
||||
local t__val1="$1"; shift
|
||||
local t__op="$1"; shift
|
||||
local t__val2="$(evalp "$@")"
|
||||
eval '[[ "$t__val1" '"$t__op"' "$t__val2" ]]'
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.init "Fonctions de base: initialiser l'environnement"
|
||||
|
||||
if [ -z "$NUCORE_NO_INIT_ENV" ]; then
|
||||
# Emplacement du script courant
|
||||
if [ "$0" == "-bash" ]; then
|
||||
MYNAME=
|
||||
MYDIR=
|
||||
MYSELF=
|
||||
elif [ ! -f "$0" -a -f "${0#-}" ]; then
|
||||
MYNAME="$(basename -- "${0#-}")"
|
||||
MYDIR="$(dirname -- "${0#-}")"
|
||||
MYDIR="$(cd "$MYDIR"; pwd)"
|
||||
MYSELF="$MYDIR/$MYNAME"
|
||||
else
|
||||
MYNAME="$(basename -- "$0")"
|
||||
MYDIR="$(dirname -- "$0")"
|
||||
MYDIR="$(cd "$MYDIR"; pwd)"
|
||||
MYSELF="$MYDIR/$MYNAME"
|
||||
fi
|
||||
[ -n "$NUCOREDIR" ] || NUCOREDIR="$MYDIR"
|
||||
|
||||
# Repertoire temporaire
|
||||
[ -z "$TMPDIR" -a -d "$HOME/tmp" ] && TMPDIR="$HOME/tmp"
|
||||
[ -z "$TMPDIR" ] && TMPDIR="${TMP:-${TEMP:-/tmp}}"
|
||||
export TMPDIR
|
||||
|
||||
# User
|
||||
[ -z "$USER" -a -n "$LOGNAME" ] && export USER="$LOGNAME"
|
||||
|
||||
# Le fichier nucorerc doit être chargé systématiquement
|
||||
[ -f /etc/debian_chroot ] && NUCORE_CHROOT=1
|
||||
[ -f /etc/nucorerc ] && . /etc/nucorerc
|
||||
[ -f ~/.nucorerc ] && . ~/.nucorerc
|
||||
|
||||
# Type de système sur lequel tourne le script
|
||||
UNAME_SYSTEM=`uname -s`
|
||||
[ "${UNAME_SYSTEM#CYGWIN}" != "$UNAME_SYSTEM" ] && UNAME_SYSTEM=Cygwin
|
||||
[ "${UNAME_SYSTEM#MINGW32}" != "$UNAME_SYSTEM" ] && UNAME_SYSTEM=Mingw
|
||||
UNAME_MACHINE=`uname -m`
|
||||
if [ -n "$NUCORE_CHROOT" ]; then
|
||||
# Dans un chroot, il est possible de forcer les valeurs
|
||||
[ -n "$NUCORE_UNAME_SYSTEM" ] && eval "UNAME_SYSTEM=$NUCORE_UNAME_SYSTEM"
|
||||
[ -n "$NUCORE_UNAME_MACHINE" ] && eval "UNAME_MACHINE=$NUCORE_UNAME_MACHINE"
|
||||
fi
|
||||
|
||||
# Nom d'hôte respectivement avec et sans domaine
|
||||
# contrairement à $HOSTNAME, cette valeur peut être spécifiée, comme par ruinst
|
||||
[ -n "$MYHOST" ] || MYHOST="$HOSTNAME"
|
||||
[ -n "$MYHOSTNAME" ] || MYHOSTNAME="${HOSTNAME%%.*}"
|
||||
export MYHOST MYHOSTNAME
|
||||
fi
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,158 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.path "Fonctions de base: gestion des chemins et des fichiers"
|
||||
require: base.core
|
||||
|
||||
function: in_path "tester l'existence d'un programme dans le PATH"
|
||||
function in_path() {
|
||||
[ -n "$1" -a -x "$(which "$1" 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
function: delpath "supprimer le chemin \$1 de \$2(=PATH)"
|
||||
function delpath() {
|
||||
local _qdir="${1//\//\\/}"
|
||||
eval "export ${2:-PATH}; ${2:-PATH}"'="${'"${2:-PATH}"'#$1:}"; '"${2:-PATH}"'="${'"${2:-PATH}"'%:$1}"; '"${2:-PATH}"'="${'"${2:-PATH}"'//:$_qdir:/:}"; [ "$'"${2:-PATH}"'" == "$1" ] && '"${2:-PATH}"'='
|
||||
}
|
||||
|
||||
function: addpath "Ajouter le chemin \$1 à la fin, dans \$2(=PATH), s'il n'y existe pas déjà"
|
||||
function addpath() {
|
||||
local _qdir="${1//\//\\/}"
|
||||
eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="${'"${2:-PATH}"':+$'"${2:-PATH}"':}$1"'
|
||||
}
|
||||
|
||||
function: inspathm "Ajouter le chemin \$1 au début, dans \$2(=PATH), s'il n'y existe pas déjà"
|
||||
function inspathm() {
|
||||
local _qdir="${1//\//\\/}"
|
||||
eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="$1${'"${2:-PATH}"':+:$'"${2:-PATH}"'}"'
|
||||
}
|
||||
|
||||
function: inspath "S'assurer que le chemin \$1 est au début de \$2(=PATH)"
|
||||
function inspath() {
|
||||
delpath "$@"
|
||||
inspathm "$@"
|
||||
}
|
||||
|
||||
function: push_cwd "enregistrer le répertoire courant dans la variable \$2(=cwd) et se placer dans le répertoire \$1"
|
||||
function push_cwd() {
|
||||
eval "${2:-cwd}"'="$(pwd)"'
|
||||
cd "$1"
|
||||
}
|
||||
function: pop_cwd "se placer dans le répertoire \${!\$2}(=\$cwd) puis retourner le code d'erreur \$1(=0)"
|
||||
function pop_cwd() {
|
||||
eval 'cd "$'"${2:-cwd}"'"'
|
||||
return "${1:-0}"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## fichiers temporaires
|
||||
|
||||
function: mktempf "générer un fichier temporaire et retourner son nom"
|
||||
function mktempf() {
|
||||
mktemp "${1:-"$TMPDIR/tmp.XXXXXX"}"
|
||||
}
|
||||
|
||||
function: mktempd "générer un répertoire temporaire et retourner son nom"
|
||||
function mktempd() {
|
||||
mktemp -d "${1:-"$TMPDIR/tmp.XXXXXX"}"
|
||||
}
|
||||
|
||||
function ac__forgetall() { NUCORE__AC_FILES=(); }
|
||||
ac__forgetall
|
||||
function ac__trap() {
|
||||
local file
|
||||
for file in "${NUCORE__AC_FILES[@]}"; do
|
||||
[ -e "$file" ] && rm -rf "$file" 2>/dev/null
|
||||
done
|
||||
ac__forgetall
|
||||
}
|
||||
trap ac__trap 1 3 15 EXIT
|
||||
|
||||
function: autoclean "\
|
||||
Ajouter les fichiers spécifiés à la liste des fichiers à supprimer à la fin du
|
||||
programme"
|
||||
function autoclean() {
|
||||
local file
|
||||
for file in "$@"; do
|
||||
[ -n "$file" ] && NUCORE__AC_FILES=("${NUCORE__AC_FILES[@]}" "$file")
|
||||
done
|
||||
}
|
||||
|
||||
function: ac_cleanall "\
|
||||
Supprimer *tous* les fichiers temporaires gérés par autoclean tout de suite."
|
||||
function ac_cleanall() {
|
||||
ac__trap
|
||||
}
|
||||
|
||||
function: ac_clean "\
|
||||
Supprimer les fichier temporaires \$1..@ si et seulement s'ils ont été générés
|
||||
par ac_set_tmpfile() ou ac_set_tmpdir()"
|
||||
function ac_clean() {
|
||||
local file acfile found
|
||||
local -a acfiles
|
||||
for acfile in "${NUCORE__AC_FILES[@]}"; do
|
||||
found=
|
||||
for file in "$@"; do
|
||||
if [ "$file" == "$acfile" ]; then
|
||||
found=1
|
||||
[ -e "$file" ] && rm -rf "$file" 2>/dev/null
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -z "$found" ] && acfiles=("${acfiles[@]}" "$acfile")
|
||||
done
|
||||
NUCORE__AC_FILES=("${acfiles[@]}")
|
||||
}
|
||||
|
||||
function: ac_set_tmpfile "\
|
||||
Créer un fichier temporaire avec le motif \$2, l'ajouter à la liste des
|
||||
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
|
||||
variable \$1
|
||||
|
||||
En mode debug, si (\$5 est vide ou \${!5} est une valeur vraie), et si \$3 n'est
|
||||
pas vide, prendre ce fichier au lieu de générer un nouveau fichier temporaire.
|
||||
Si \$4==keep, ne pas écraser le fichier \$3 s'il existe."
|
||||
function ac_set_tmpfile() {
|
||||
local se__d
|
||||
if is_debug; then
|
||||
if [ -n "$5" ]; then
|
||||
is_yes "${!5}" && se__d=1
|
||||
else
|
||||
se__d=1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$se__d" -a -n "$3" ]; then
|
||||
_setv "$1" "$3"
|
||||
[ -f "$3" -a "$4" == keep ] || >"$3"
|
||||
else
|
||||
local se__t="$(mktempf "$2")"
|
||||
autoclean "$se__t"
|
||||
_setv "$1" "$se__t"
|
||||
fi
|
||||
}
|
||||
|
||||
function: ac_set_tmpdir "\
|
||||
Créer un répertoire temporaire avec le motif \$2, l'ajouter à la liste des
|
||||
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
|
||||
variable \$1
|
||||
|
||||
En mode debug, si (\$4 est vide ou \${!4} est une valeur vraie), et si \$3 n'est
|
||||
pas vide, prendre ce nom de répertoire au lieu de créer un nouveau répertoire
|
||||
temporaire"
|
||||
function ac_set_tmpdir() {
|
||||
local sr__d
|
||||
if is_debug; then
|
||||
if [ -n "$4" ]; then
|
||||
is_yes "${!4}" && sr__d=1
|
||||
else
|
||||
sr__d=1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$sr__d" -a -n "$3" ]; then
|
||||
_setv "$1" "$3"
|
||||
mkdir -p "$3"
|
||||
else
|
||||
local sr__t="$(mktempd "$2")"
|
||||
autoclean "$sr__t"
|
||||
_setv "$1" "$sr__t"
|
||||
fi
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
# shim pour les fonctions de nucore.sh au cas où ce module n'est pas chargée
|
||||
if [ -z "$NUCOREDIR" -o "$NUCOREDIR" != "$NUCOREINIT" ]; then
|
||||
function module:() { :; }
|
||||
function function:() { :; }
|
||||
function require:() { :; }
|
||||
fi
|
||||
##@include base.init.sh
|
||||
##@include base.core.sh
|
||||
##@include base.str.sh
|
||||
##@include base.arr.sh
|
||||
##@include base.io.sh
|
||||
##@include base.eval.sh
|
||||
##@include base.split.sh
|
||||
##@include base.path.sh
|
||||
##@include base.args.sh
|
||||
module: base "Chargement de tous les modules base.*"
|
||||
require: base.init base.core base.str base.arr base.io base.eval base.split base.path base.args
|
|
@ -0,0 +1,189 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.split "Fonctions de base: analyse et découpage de valeurs"
|
||||
require: base.arr
|
||||
|
||||
function: splitfsep "\
|
||||
Découper \$1 de la forme first[SEPsecond] entre first, qui est placé dans la
|
||||
variable \$3(=first) et second, qui est placée dans la variable \$4(=second). \$2
|
||||
est la valeur SEP. Le découpage est faite sur la *première* occurence de SEP."
|
||||
function splitfsep() {
|
||||
if [[ "$1" == *"$2"* ]]; then
|
||||
setv "${3:-first}" "${1%%$2*}"
|
||||
setv "${4:-second}" "${1#*$2}"
|
||||
else
|
||||
setv "${3:-first}" "$1"
|
||||
setv "${4:-second}"
|
||||
fi
|
||||
}
|
||||
|
||||
function: splitfsep2 "\
|
||||
Découper \$1 de la forme [firstSEP]second entre first, qui est placé dans la
|
||||
variable \$3(=first) et second, qui est placée dans la variable \$4(=second). \$2
|
||||
est la valeur SEP. Le découpage est faite sur la *première* occurence de SEP."
|
||||
function splitfsep2() {
|
||||
if [[ "$1" == *"$2"* ]]; then
|
||||
setv "${3:-first}" "${1%%$2*}"
|
||||
setv "${4:-second}" "${1#*$2}"
|
||||
else
|
||||
setv "${3:-first}"
|
||||
setv "${4:-second}" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
function: splitlsep "\
|
||||
Découper \$1 de la forme first[SEPsecond] entre first, qui est placé dans la
|
||||
variable \$3(=first) et second, qui est placée dans la variable \$4(=second). \$2
|
||||
est la valeur SEP. Le découpage est faite sur la *dernière* occurence de SEP."
|
||||
function splitlsep() {
|
||||
if [[ "$1" == *"$2"* ]]; then
|
||||
setv "${3:-first}" "${1%$2*}"
|
||||
setv "${4:-second}" "${1##*$2}"
|
||||
else
|
||||
setv "${3:-first}" "$1"
|
||||
setv "${4:-second}"
|
||||
fi
|
||||
}
|
||||
|
||||
function: splitlsep2 "\
|
||||
Découper \$1 de la forme [firstSEP]second entre first, qui est placé dans la
|
||||
variable \$3(=first) et second, qui est placée dans la variable \$4(=second). \$2
|
||||
est la valeur SEP. Le découpage est faite sur la *dernière* occurence de SEP."
|
||||
function splitlsep2() {
|
||||
if [[ "$1" == *"$2"* ]]; then
|
||||
setv "${3:-first}" "${1%$2*}"
|
||||
setv "${4:-second}" "${1##*$2}"
|
||||
else
|
||||
setv "${3:-first}"
|
||||
setv "${4:-second}" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
function: splitvar "\
|
||||
Découper \$1 de la forme name[=value] entre le nom, qui est placé dans la
|
||||
variable \$2(=name) et la valeur, qui est placée dans la variable \$3(=value)"
|
||||
function splitvar() {
|
||||
splitfsep "$1" = "${2:-name}" "${3:-value}"
|
||||
}
|
||||
|
||||
function: splitpath "\
|
||||
Découper \$1 de la forme [dir/]name entre le répertoire, qui est placé dans la
|
||||
variable \$2(=dir), et le nom du fichier, qui est placé dans la variable
|
||||
\$3(=name)"
|
||||
function splitpath() {
|
||||
splitlsep2 "$1" / "${2:-dir}" "${3:-name}"
|
||||
}
|
||||
|
||||
function: splitname "\
|
||||
Découper \$1 de la forme basename[.ext] entre le nom de base du fichier, qui
|
||||
est placé dans la variable \$2(=basename) et l'extension, qui est placée dans
|
||||
la variable \$3(=ext)
|
||||
|
||||
Attention, si \$1 est un chemin, le résultat risque d'être faussé. Par exemple,
|
||||
'splitname a.b/c' ne donne pas le résultat escompté."
|
||||
function splitname() {
|
||||
splitlsep "$1" . "${2:-basename}" "${3:-ext}"
|
||||
}
|
||||
|
||||
function: splithost "\
|
||||
Découper \$1 de la forme hostname[.domain] entre le nom d'hôte, qui est placé
|
||||
dans la variable \$2(=hostname) et le domaine, qui est placée dans la variable
|
||||
\$3(=domain)"
|
||||
function splithost() {
|
||||
splitfsep "$1" . "${2:-hostname}" "${3:-domain}"
|
||||
}
|
||||
|
||||
function: splituserhost "\
|
||||
Découper \$1 de la forme [user@]host entre le nom de l'utilisateur, qui est placé
|
||||
dans la variable \$2(=user) et le nom d'hôte, qui est placée dans la variable
|
||||
\$3(=host)"
|
||||
function splituserhost() {
|
||||
splitfsep2 "$1" @ "${2:-user}" "${3:-host}"
|
||||
}
|
||||
|
||||
function: splitpair "\
|
||||
Découper \$1 de la forme first[:second] entre la première valeur, qui est placé
|
||||
dans la variable \$2(=src) et la deuxième valeur, qui est placée dans la variable
|
||||
\$3(=dest)"
|
||||
function splitpair() {
|
||||
splitfsep "$1" : "${2:-src}" "${3:-dest}"
|
||||
}
|
||||
|
||||
function: splitproxy "\
|
||||
Découper \$1 de la forme http://[user:password@]host[:port]/ entre les valeurs
|
||||
\$2(=host), \$3(=port), \$4(=user), \$5(=password)
|
||||
|
||||
S'il n'est pas spécifié, port vaut 3128 par défaut"
|
||||
function splitproxy() {
|
||||
local sy__tmp sy__host sy__port sy__creds sy__user sy__password
|
||||
|
||||
sy__tmp="${1#http://}"
|
||||
if [[ "$sy__tmp" == *@* ]]; then
|
||||
sy__creds="${sy__tmp%%@*}"
|
||||
sy__tmp="${sy__tmp#${sy__creds}@}"
|
||||
splitpair "$sy__creds" sy__user sy__password
|
||||
fi
|
||||
sy__tmp="${sy__tmp%%/*}"
|
||||
splitpair "$sy__tmp" sy__host sy__port
|
||||
[ -n "$sy__port" ] || sy__port=3128
|
||||
|
||||
setv "${2:-host}" "$sy__host"
|
||||
setv "${3:-port}" "$sy__port"
|
||||
setv "${4:-user}" "$sy__user"
|
||||
setv "${5:-password}" "$sy__password"
|
||||
}
|
||||
|
||||
function: spliturl "\
|
||||
Découper \$1 de la forme scheme://[user:password@]host[:port]/path entre les
|
||||
valeurs \$2(=scheme), \$3(=user), \$4(=password), \$5(=host), \$6(=port), \$7(=path)
|
||||
|
||||
S'il n'est pas spécifié, port vaut 80 pour http, 443 pour https, 21 pour ftp"
|
||||
function spliturl() {
|
||||
local sl__tmp sl__scheme sl__creds sl__user sl__password sl__host sl__port sl__path
|
||||
|
||||
sl__scheme="${1%%:*}"
|
||||
sl__tmp="${1#${sl__scheme}://}"
|
||||
if [[ "$sl__tmp" == */* ]]; then
|
||||
sl__path="${sl__tmp#*/}"
|
||||
sl__tmp="${sl__tmp%%/*}"
|
||||
fi
|
||||
if [[ "$sl__tmp" == *@* ]]; then
|
||||
sl__creds="${sl__tmp%%@*}"
|
||||
sl__tmp="${sl__tmp#${sl__creds}@}"
|
||||
splitpair "$sl__creds" sl__user sl__password
|
||||
fi
|
||||
splitpair "$sl__tmp" sl__host sl__port
|
||||
if [ -z "$sl__port" ]; then
|
||||
[ "$sl__scheme" == "http" ] && sl__port=80
|
||||
[ "$sl__scheme" == "https" ] && sl__port=443
|
||||
[ "$sl__scheme" == "ftp" ] && sl__port=21
|
||||
fi
|
||||
|
||||
setv "${2:-scheme}" "$sl__scheme"
|
||||
setv "${3:-user}" "$sl__user"
|
||||
setv "${4:-password}" "$sl__password"
|
||||
setv "${5:-host}" "$sl__host"
|
||||
setv "${6:-port}" "$sl__port"
|
||||
setv "${7:-path}" "$sl__path"
|
||||
}
|
||||
|
||||
function: splitwcs "\
|
||||
Découper un nom de chemin \$1 entre la partie sans wildcards, qui est placée dans
|
||||
la variables \$2(=basedir), et la partie avec wildcards, qui est placée dans la
|
||||
variable \$3(=filespec)"
|
||||
function splitwcs() {
|
||||
local ss__p="$1"
|
||||
local ss__dd="${2:-basedir}" ss__df="${3:-filespec}" ss__part ss__d ss__f
|
||||
local -a ss__parts
|
||||
array_split ss__parts "$ss__p" "/"
|
||||
for ss__part in "${ss__parts[@]}"; do
|
||||
if [[ "$ss__part" == *\** ]] || [[ "$ss__part" == *\?* ]] || [ -n "$ss__f" ]; then
|
||||
ss__f="${ss__f:+$ss__f/}$ss__part"
|
||||
else
|
||||
ss__d="${ss__d:+$ss__d/}$ss__part"
|
||||
fi
|
||||
done
|
||||
[ "${ss__p#/}" != "$ss__p" ] && ss__d="/$ss__d"
|
||||
_setv "$ss__dd" "$ss__d"
|
||||
_setv "$ss__df" "$ss__f"
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: base.str "Fonctions de base: gestion des valeurs chaines"
|
||||
|
||||
function: strmid "Afficher la plage \$1 de la valeur \$2..*
|
||||
|
||||
La plage peut être d'une des formes 'start', '[start]:length'. Si start est
|
||||
négatif, le compte est effectué à partir de la fin de la chaine. Si length est
|
||||
négatif, il est rajouté à la longueur de la chaine à partir de start"
|
||||
function strmid() {
|
||||
local range="$1"; shift
|
||||
local str="$*"
|
||||
if [[ "$range" == *:-* ]]; then
|
||||
local max=${#str}
|
||||
[ $max -eq 0 ] && return
|
||||
local start="${range%%:*}"
|
||||
[ -n "$start" ] || start=0
|
||||
while [ "$start" -lt 0 ]; do
|
||||
start=$(($max$start))
|
||||
done
|
||||
max=$(($max-$start))
|
||||
local length="${range#*:}"
|
||||
while [ "$length" -lt 0 ]; do
|
||||
length=$(($max$length))
|
||||
done
|
||||
range="$start:$length"
|
||||
fi
|
||||
eval 'echo "${str:'" $range"'}"'
|
||||
}
|
||||
|
||||
function: strrepl "Remplacer dans la valeur \$3..* le motif \$1 par la chaine \$2
|
||||
|
||||
\$1 peut commencer par l'un des caractères /, #, % pour indiquer le type de recherche"
|
||||
function strrepl() {
|
||||
local pattern="$1"; shift
|
||||
local repl="$1"; shift
|
||||
local str="$*"
|
||||
local cmd='echo "${str/'
|
||||
if [ "${pattern#/}" != "$pattern" ]; then
|
||||
pattern="${pattern#/}"
|
||||
cmd="$cmd/"
|
||||
elif [ "${pattern#\#}" != "$pattern" ]; then
|
||||
pattern="${pattern#\#}"
|
||||
cmd="$cmd#"
|
||||
elif [ "${pattern#%}" != "$pattern" ]; then
|
||||
pattern="${pattern#%}"
|
||||
cmd="$cmd%"
|
||||
fi
|
||||
cmd="$cmd"'$pattern/$repl}"'
|
||||
eval "$cmd"
|
||||
}
|
||||
|
||||
function: strlcomp "transformer dans le flux en entrée en UTF-8 certains caractères en leur équivalent transformable en latin1.
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function strlcomp() {
|
||||
if [ $# -gt 0 ]; then strlcomp <<<"$*"
|
||||
else LANG=fr_FR.UTF-8 sed $'
|
||||
s/[\xE2\x80\x90\xE2\x80\x91\xE2\x80\x92\xE2\x80\x93\xE2\x80\x94\xE2\x80\x95]/-/g
|
||||
s/[‘’]/\x27/g
|
||||
s/[«»“”]/"/g
|
||||
s/[\xC2\xA0\xE2\x80\x87\xE2\x80\xAF\xE2\x81\xA0]/ /g
|
||||
s/[\xE2\x80\xA6]/.../g
|
||||
s/[œ]/oe/g
|
||||
s/[Œ]/OE/g
|
||||
s/[æ]/ae/g
|
||||
s/[Æ]/AE/g
|
||||
s/a\xCC\x80/à/g
|
||||
s/e\xCC\x81/é/g; s/e\xCC\x80/è/g; s/e\xCC\x82/ê/g; s/e\xCC\x88/ë/g
|
||||
s/i\xCC\x88/ï/g; s/i\xCC\x82/î/g
|
||||
s/o\xCC\x82/ô/g; s/o\xCC\x88/ö/g
|
||||
s/u\xCC\x88/ü/g; s/u\xCC\x82/û/g
|
||||
s/c\xCC\xA7/ç/g
|
||||
s/A\xCC\x80/À/g
|
||||
s/E\xCC\x81/É/g; s/E\xCC\x80/È/g; s/E\xCC\x82/Ê/g; s/E\xCC\x88/Ë/g
|
||||
s/I\xCC\x88/Ï/g; s/I\xCC\x82/Î/g
|
||||
s/O\xCC\x82/Ô/g; s/O\xCC\x88/Ö/g
|
||||
s/U\xCC\x88/Ü/g; s/U\xCC\x82/Û/g
|
||||
s/C\xCC\xA7/Ç/g
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
function: strnacc "supprimer les accents dans le flux en entrée en UTF-8
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function strnacc() {
|
||||
if [ $# -gt 0 ]; then strnacc <<<"$*"
|
||||
else LANG=fr_FR.UTF-8 sed '
|
||||
s/[à]/a/g
|
||||
s/[éèêë]/e/g
|
||||
s/[ïî]/i/g
|
||||
s/[ôö]/o/g
|
||||
s/[üû]/u/g
|
||||
s/[ç]/c/g
|
||||
s/[À]/A/g
|
||||
s/[ÉÈÊË]/E/g
|
||||
s/[ÏÎ]/I/g
|
||||
s/[ÔÖ]/O/g
|
||||
s/[ÜÛ]/U/g
|
||||
s/[Ç]/C/g
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
function: stripnl "Supprimer dans le flux en entrée les caractères de fin de ligne
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function stripnl() {
|
||||
if [ $# -gt 0 ]; then stripnl <<<"$*"
|
||||
else tr -d '\r\n'
|
||||
fi
|
||||
}
|
||||
|
||||
function: nl2lf "transformer dans le flux en entrée les fins de ligne en LF
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function nl2lf() {
|
||||
if [ $# -gt 0 ]; then nl2lf <<<"$*"
|
||||
else lawk 'BEGIN {RS="\r|\r\n|\n"} {print}'
|
||||
fi
|
||||
}
|
||||
|
||||
function: nl2crlf "transformer dans le flux en entrée les fins de ligne en CRLF
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function nl2crlf() {
|
||||
if [ $# -gt 0 ]; then nl2crlf <<<"$*"
|
||||
else lawk 'BEGIN {RS="\r|\r\n|\n"} {print $0 "\r"}'
|
||||
fi
|
||||
}
|
||||
|
||||
function: nl2cr "transformer dans le flux en entrée les fins de ligne en CR
|
||||
|
||||
si cette fonction est appelée avec des arguments, prendre \$* comme valeur du flux en entrée."
|
||||
function nl2cr() {
|
||||
if [ $# -gt 0 ]; then nl2cr <<<"$*"
|
||||
else lawk 'BEGIN {RS="\r|\r\n|\n"; ORS=""} {print $0 "\r"}'
|
||||
fi
|
||||
}
|
|
@ -0,0 +1,704 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
##@require nucore.sh
|
||||
##@require base
|
||||
module: git "Fonctions pour faciliter l'utilisation de git"
|
||||
require: nucore base
|
||||
|
||||
function: git_geturl ""
|
||||
function git_geturl() {
|
||||
git config --get remote.origin.url
|
||||
}
|
||||
|
||||
function: git_have_annex ""
|
||||
function git_have_annex() {
|
||||
[ -n "$(git config --get annex.uuid)" ]
|
||||
}
|
||||
|
||||
NUCORE_GIT_FUNCTIONS=(
|
||||
git_check_gitvcs git_ensure_gitvcs
|
||||
git_list_branches git_list_rbranches
|
||||
git_have_branch git_have_rbranch
|
||||
git_get_branch git_is_branch
|
||||
git_have_remote git_track_branch
|
||||
git_check_cleancheckout git_ensure_cleancheckout
|
||||
git_is_ancestor git_should_ff git_should_push
|
||||
git_is_merged
|
||||
)
|
||||
NUCORE_GIT_FUNCTIONS_MAP=(
|
||||
cg:git_check_gitvcs eg:git_ensure_gitvcs
|
||||
lbs:git_list_branches rbs:git_list_rbranches
|
||||
hlb:git_have_branch hrb:git_have_rbranch
|
||||
gb:git_get_branch ib:git_is_branch
|
||||
hr:git_have_remote tb:git_track_branch
|
||||
cc:git_check_cleancheckout ec:git_ensure_cleancheckout
|
||||
ia:git_is_ancestor sff:git_should_ff spu:git_should_push
|
||||
im:git_is_merged
|
||||
)
|
||||
|
||||
function: git_check_gitvcs ""
|
||||
function git_check_gitvcs() {
|
||||
git rev-parse --show-toplevel >&/dev/null
|
||||
}
|
||||
|
||||
function: git_ensure_gitvcs ""
|
||||
function git_ensure_gitvcs() {
|
||||
git_check_gitvcs || edie "Ce n'est pas un dépôt git" || return
|
||||
}
|
||||
|
||||
function: git_list_branches ""
|
||||
function git_list_branches() {
|
||||
git for-each-ref refs/heads/ --format='%(refname:short)' | csort
|
||||
}
|
||||
|
||||
function: git_list_rbranches ""
|
||||
function git_list_rbranches() {
|
||||
git for-each-ref "refs/remotes/${1:-origin}/" --format='%(refname:short)' | csort
|
||||
}
|
||||
|
||||
function: git_list_pbranches "lister les branches locales et celles qui existent dans l'origine \$1(=origin) et qui pourraient devenir une branche locale avec la commande git checkout -b"
|
||||
function git_list_pbranches() {
|
||||
local prefix="${1:-origin}/"
|
||||
{
|
||||
git for-each-ref refs/heads/ --format='%(refname:short)'
|
||||
git for-each-ref "refs/remotes/$prefix" --format='%(refname:short)' | grep -F "$prefix" | cut -c $((${#prefix} + 1))-
|
||||
} | grep -vF HEAD | csort -u
|
||||
}
|
||||
|
||||
function: git_have_branch ""
|
||||
function git_have_branch() {
|
||||
git_list_branches | grep -qF "$1"
|
||||
}
|
||||
|
||||
function: git_have_rbranch ""
|
||||
function git_have_rbranch() {
|
||||
git_list_rbranches "${2:-origin}" | grep -qF "$1"
|
||||
}
|
||||
|
||||
function: git_get_branch ""
|
||||
function git_get_branch() {
|
||||
git rev-parse --abbrev-ref HEAD 2>/dev/null
|
||||
}
|
||||
|
||||
function: git_get_branch_remote ""
|
||||
function git_get_branch_remote() {
|
||||
local branch="$1"
|
||||
[ -n "$branch" ] || branch="$(git_get_branch)"
|
||||
[ -n "$branch" ] || return
|
||||
git config --get "branch.$branch.remote"
|
||||
}
|
||||
|
||||
function: git_get_branch_merge ""
|
||||
function git_get_branch_merge() {
|
||||
local branch="$1"
|
||||
[ -n "$branch" ] || branch="$(git_get_branch)"
|
||||
[ -n "$branch" ] || return
|
||||
git config --get "branch.$branch.merge"
|
||||
}
|
||||
|
||||
function: git_get_branch_rbranch ""
|
||||
function git_get_branch_rbranch() {
|
||||
local branch="$1" remote="$2" merge
|
||||
[ -n "$branch" ] || branch="$(git_get_branch)"
|
||||
[ -n "$branch" ] || return
|
||||
[ -n "$remote" ] || remote="$(git_get_branch_remote "$branch")"
|
||||
[ -n "$remote" ] || return
|
||||
merge="$(git_get_branch_merge "$branch")"
|
||||
[ -n "$merge" ] || return
|
||||
echo "refs/remotes/$remote/${merge#refs/heads/}"
|
||||
}
|
||||
|
||||
function: git_is_branch ""
|
||||
function git_is_branch() {
|
||||
[ "$(git_get_branch)" == "${1:-master}" ]
|
||||
}
|
||||
|
||||
function: git_have_remote ""
|
||||
function git_have_remote() {
|
||||
[ -n "$(git config --get remote.${1:-origin}.url)" ]
|
||||
}
|
||||
|
||||
function: git_track_branch ""
|
||||
function git_track_branch() {
|
||||
local branch="$1" origin="${2:-origin}"
|
||||
[ -n "$branch" ] || return
|
||||
git_have_remote "$origin" || return
|
||||
[ "$(git config --get branch.$branch.remote)" == "$origin" ] && return
|
||||
if git_have_rbranch "$branch" "$origin"; then
|
||||
if git_have_branch "$branch"; then
|
||||
git branch -u "$origin/$branch" "$branch"
|
||||
else
|
||||
git branch -t "$branch" "$origin/$branch"
|
||||
fi
|
||||
elif git_have_branch "$branch"; then
|
||||
git push -u "$origin" "$branch" || return
|
||||
fi
|
||||
}
|
||||
|
||||
function: git_ensure_branch "
|
||||
@return 0 si la branche a été créée, 1 si elle existait déjà, 2 en cas d'erreur"
|
||||
function git_ensure_branch() {
|
||||
local branch="$1" source="${2:-master}" origin="${3:-origin}"
|
||||
[ -n "$branch" ] || return 2
|
||||
git_have_branch "$branch" && return 1
|
||||
if git_have_rbranch "$branch" "$origin"; then
|
||||
# une branche du même nom existe dans l'origine. faire une copie de cette branche
|
||||
git branch -t "$branch" "$origin/$branch" || return 2
|
||||
else
|
||||
# créer une nouvelle branche du nom spécifié
|
||||
git_have_branch "$source" || return 2
|
||||
git branch "$branch" "$source" || return 2
|
||||
if [ -z "$NUCORE_GIT_OFFLINE" ]; then
|
||||
git_have_remote "$origin" && git_track_branch "$branch" "$origin"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function: git_check_cleancheckout "vérifier qu'il n'y a pas de modification locales dans le dépôt correspondant au répertoire courant."
|
||||
function git_check_cleancheckout() {
|
||||
[ -z "$(git status --porcelain 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
function: git_ensure_cleancheckout ""
|
||||
function git_ensure_cleancheckout() {
|
||||
git_check_cleancheckout ||
|
||||
edie "Vous avez des modifications locales. Enregistrez ces modifications avant de continuer" || return
|
||||
}
|
||||
|
||||
function git__init_ff() {
|
||||
o="${3:-origin}"
|
||||
b="$1" s="${2:-refs/remotes/$o/$1}"
|
||||
b="$(git rev-parse --verify --quiet "$b")" || return 1
|
||||
s="$(git rev-parse --verify --quiet "$s")" || return 1
|
||||
return 0
|
||||
}
|
||||
function git__can_ff() {
|
||||
[ "$1" == "$(git merge-base "$1" "$2")" ]
|
||||
}
|
||||
|
||||
function: git_is_ancestor "vérifier que la branche \$1 est un ancêtre direct de la branche \$2, qui vaut par défaut refs/remotes/\${3:-origin}/\$1
|
||||
note: cette fonction retourne vrai si \$1 et \$2 identifient le même commit"
|
||||
function git_is_ancestor() {
|
||||
local o b s; git__init_ff "$@" || return
|
||||
git__can_ff "$b" "$s"
|
||||
}
|
||||
|
||||
function: git_should_ff "vérifier si la branche \$1 devrait être fast-forwardée à partir de la branche d'origine \$2, qui vaut par défaut refs/remotes/\${3:-origin}/\$1
|
||||
note: cette fonction est similaire à git_is_ancestor(), mais retourne false si \$1 et \$2 identifient le même commit"
|
||||
function git_should_ff() {
|
||||
local o b s; git__init_ff "$@" || return
|
||||
[ "$b" != "$s" ] || return 1
|
||||
git__can_ff "$b" "$s"
|
||||
}
|
||||
|
||||
function: git_should_push "vérifier si la branche \$1 devrait être poussée vers la branche de même nom dans l'origine \$2(=origin), parce que l'origin peut-être fast-forwardée à partir de cette branche."
|
||||
function git_should_push() {
|
||||
git_should_ff "refs/remotes/${2:-origin}/$1" "$1"
|
||||
}
|
||||
|
||||
function: git_fast_forward "vérifier que la branche courante est bien \$1, puis tester s'il faut la fast-forwarder à partir de la branche d'origine \$2, puis le faire si c'est nécessaire. la branche d'origine \$2 vaut par défaut refs/remotes/origin/\$1"
|
||||
function git_fast_forward() {
|
||||
local o b s; git__init_ff "$@" || return
|
||||
[ "$b" != "$s" ] || return 1
|
||||
local head="$(git rev-parse HEAD)"
|
||||
[ "$head" == "$b" ] || return 1
|
||||
git__can_ff "$b" "$s" || return 1
|
||||
git merge --ff-only "$s"
|
||||
}
|
||||
|
||||
function: git_is_merged "vérifier que les branches \$1 et \$2 ont un ancêtre commun, et que la branche \$1 a été complètement fusionnée dans la branche destination \$2"
|
||||
function git_is_merged() {
|
||||
local b="$1" d="$2"
|
||||
b="$(git rev-parse --verify --quiet "$b")" || return 1
|
||||
d="$(git rev-parse --verify --quiet "$d")" || return 1
|
||||
[ -n "$(git merge-base "$b" "$d")" ] || return 1
|
||||
[ -z "$(git rev-list "$d..$b")" ]
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# git annex
|
||||
|
||||
NUCORE_GIT_SSH_WRAPPER=
|
||||
function: git_annex_use_ssh_wrapper ""
|
||||
function git_annex_use_ssh_wrapper() {
|
||||
[ -n "$NUCORE_GIT_SSH_WRAPPER" ] && return
|
||||
NUCORE_GIT_FORCE_PATH="$PATH"
|
||||
NUCORE_GIT_FORCE_SSH="${GIT_SSH:-ssh}"
|
||||
export NUCORE_GIT_FORCE_PATH NUCORE_GIT_FORCE_SSH
|
||||
base_delpath "$NUCOREDIR/ssh-wrapper" NUCORE_GIT_FORCE_PATH
|
||||
base_inspath "$NUCOREDIR/ssh-wrapper" PATH
|
||||
NUCORE_GIT_SSH_WRAPPER=1
|
||||
}
|
||||
|
||||
function: git_annex_initial "sur le dépôt \$1 fraichement cloné, vérifier s'il faut faire git annex init. Si oui, l'initialiser avec le nom d'hôte, et récupérer tous les fichiers annexés
|
||||
@return 1 si une erreur s'est produite"
|
||||
function git_annex_initial() {
|
||||
local repodir="${1:-.}"
|
||||
[ -d "$repodir" ] || return 1
|
||||
repodir="$(abspath "$repodir")"
|
||||
|
||||
local GIT_DIR GIT_WORK_TREE
|
||||
[ "$(cd "$repodir"; git rev-parse --is-bare-repository)" == false ] || return 0
|
||||
[ -n "$(GIT_DIR="$repodir/.git" git config --get annex.uuid)" ] && return 0
|
||||
|
||||
# ici, on sait que git annex n'a pas encore été configuré
|
||||
# vérifier s'il existe des fichiers annexés
|
||||
local -a links
|
||||
base_array_splitl links "$(find "$repodir" -type l)"
|
||||
local link hasannex=
|
||||
for link in "${links[@]}"; do
|
||||
link="$(readlink "$link")"
|
||||
if [ "${link#.git/annex/}" != "$link" ]; then
|
||||
hasannex=1
|
||||
break
|
||||
elif [[ "$link" == */.git/annex/* ]]; then
|
||||
hasannex=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$hasannex" ]; then
|
||||
base_in_path git-annex || edie "Vous devez installer git-annex" || return
|
||||
local cwd; base_push_cwd "$repodir" &&
|
||||
git annex init "$MYHOSTNAME" &&
|
||||
git annex get &&
|
||||
git annex sync &&
|
||||
base_pop_cwd || base_pop_cwd 1 || return
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Outils de haut niveau
|
||||
|
||||
function: git_commit ""
|
||||
function git_commit() {
|
||||
local all=auto allnew push=auto nopush args
|
||||
setyesval nopush "$NUCORE_GIT_OFFLINE"
|
||||
[ -n "$nopush" ] && push=
|
||||
parse_opts + "${PRETTYOPTS[@]}" \
|
||||
-a,--all all=1 \
|
||||
-A,--all-new allnew=1 \
|
||||
-c,--cached all= \
|
||||
-p,--push push=1 \
|
||||
-l,--local push= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || {
|
||||
eerror "$args"
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -n "$allnew" ]; then
|
||||
git add -A
|
||||
all=
|
||||
fi
|
||||
|
||||
local message="$1"; shift
|
||||
local -a cmd
|
||||
cmd=(git commit)
|
||||
[ -n "$message" ] && cmd=("${cmd[@]}" -m "$message")
|
||||
if [ "$all" == "auto" ]; then
|
||||
# Si des fichiers sont spécifiés, prendre ceux-là.
|
||||
if [ -z "$*" ]; then
|
||||
# Sinon, s'il y a des fichiers dans l'index, commiter uniquement ces
|
||||
# fichiers
|
||||
# Sinon, committer tous les fichiers modifiés
|
||||
# le code suivant retourne vrai si l'index contient au moins fichier
|
||||
git status --porcelain 2>/dev/null | lawk '
|
||||
BEGIN { ec = 1 }
|
||||
substr($0, 1, 1) ~ /[^ ?]/ { ec = 0; exit }
|
||||
END { exit ec }' ||
|
||||
cmd=("${cmd[@]}" -a)
|
||||
fi
|
||||
else
|
||||
[ -n "$all" ] && cmd=("${cmd[@]}" -a)
|
||||
fi
|
||||
|
||||
if ! "${cmd[@]}" "$@"; then
|
||||
[ "$push" == auto ] && return 1
|
||||
fi
|
||||
if [ "$push" == auto ]; then
|
||||
git_push --auto || return
|
||||
elif [ -n "$push" ]; then
|
||||
git_push --force || return
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function: git_update ""
|
||||
function git_update() {
|
||||
local args autoff=1
|
||||
parse_opts + "${PRETTYOPTS[@]}" \
|
||||
-n,--no-autoff autoff= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || {
|
||||
eerror "$args"
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -z "$autoff" ]; then
|
||||
git pull "$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
local branch orig_branch restore_branch remote rbranch pbranch
|
||||
local -a branches prbranches crbranches dbranches
|
||||
|
||||
base_array_splitl prbranches "$(git_list_rbranches)"
|
||||
git fetch -p "$@" || return
|
||||
base_array_splitl crbranches "$(git_list_rbranches)"
|
||||
|
||||
# vérifier s'il n'y a pas des branches distantes qui ont été supprimées
|
||||
for branch in "${prbranches[@]}"; do
|
||||
if ! base_array_contains crbranches "$branch"; then
|
||||
base_array_add dbranches "${branch#*/}"
|
||||
fi
|
||||
done
|
||||
if [ ${#dbranches[*]} -gt 0 ]; then
|
||||
eimportant "One or more distant branches where deleted"
|
||||
for branch in "${dbranches[@]}"; do
|
||||
if git_have_branch "$branch"; then
|
||||
if ! ask_yesno "Do you want to delete local branch $branch?" X; then
|
||||
base_array_del dbranches "$branch"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ ${#dbranches[*]} -gt 0 ]; then
|
||||
base_array_splitl branches "$(git_list_branches)"
|
||||
branch="$(git_get_branch)"
|
||||
if base_array_contains dbranches "$branch"; then
|
||||
# si la branche courante est l'une des branches à supprimer, il faut
|
||||
# basculer vers develop ou master
|
||||
local swto
|
||||
if [ -z "$swto" ] && base_array_contains branches develop && ! base_array_contains dbranches develop; then
|
||||
swto=develop
|
||||
fi
|
||||
if [ -z "$swto" ] && base_array_contains branches master && ! base_array_contains dbranches master; then
|
||||
swto=master
|
||||
fi
|
||||
if ! git_check_cleancheckout; then
|
||||
echo "* There are uncommitted local changes. However current branch is slated for removal.
|
||||
Make your verifications then delete the local branches:
|
||||
${swto:+$(qvals git checkout "$swto")
|
||||
}$(qvals git branch -D "${dbranches[@]}")"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$swto" ]; then
|
||||
git checkout -q "$swto"
|
||||
else
|
||||
echo "* Current branch is slated for removal but I don't know to which branch I should switch first.
|
||||
Make your choice then delete the local branches:
|
||||
$(qvals git branch -D "${dbranches[@]}")"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
for branch in "${dbranches[@]}"; do
|
||||
git branch -D "$branch"
|
||||
done
|
||||
fi
|
||||
|
||||
# intégrer les modifications dans les branches locales
|
||||
if ! git_check_cleancheckout; then
|
||||
branch="$(git_get_branch)"
|
||||
remote="$(git_get_branch_remote "$branch")"
|
||||
rbranch="$(git_get_branch_rbranch "$branch" "$remote")"
|
||||
pbranch="${rbranch#refs/remotes/}"
|
||||
if git merge -q --ff-only "$rbranch"; then
|
||||
echo "* There are uncommitted local changes: only CURRENT branch were updated"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
orig_branch="$(git_get_branch)"
|
||||
base_array_splitl branches "$(git_list_branches)"
|
||||
for branch in "${branches[@]}"; do
|
||||
remote="$(git_get_branch_remote "$branch")"
|
||||
rbranch="$(git_get_branch_rbranch "$branch" "$remote")"
|
||||
pbranch="${rbranch#refs/remotes/}"
|
||||
[ -n "$remote" -a -n "$rbranch" ] || continue
|
||||
if git_is_ancestor "$branch" "$rbranch"; then
|
||||
if git_should_ff "$branch" "$rbranch"; then
|
||||
echo "* Fast-forwarding $branch -> $pbranch"
|
||||
git checkout -q "$branch"
|
||||
git merge -q --ff-only "$rbranch"
|
||||
restore_branch=1
|
||||
fi
|
||||
else
|
||||
if [ "$branch" == "$orig_branch" ]; then
|
||||
echo "* Cannot fast-forward CURRENT branch $branch from $pbranch
|
||||
Try to merge manually with: git merge $pbranch"
|
||||
else
|
||||
echo "* Cannot fast-forward local branch $branch from $pbranch
|
||||
You can merge manually with: git checkout $branch; git merge $pbranch"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[ -n "$restore_branch" ] && git checkout -q "$orig_branch"
|
||||
return 0
|
||||
}
|
||||
|
||||
function: git_push ""
|
||||
function git_push() {
|
||||
local all all_branches all_tags auto force args no_annex
|
||||
parse_opts + "${PRETTYOPTS[@]}" \
|
||||
-a,--all all=1 \
|
||||
-b,--branches,--all-branches all_branches=1 \
|
||||
-t,--tags,--all-tags all_tags=1 \
|
||||
--auto auto=1 \
|
||||
-f,--force force=1 \
|
||||
-n,--no-annex no_annex=1 \
|
||||
@ args -- "$@" && set -- "${args[@]}" || {
|
||||
eerror "$args"
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -n "$all" ]; then
|
||||
# On a demandé à pusher toutes les branches et tous les tags
|
||||
local r
|
||||
git push --all "$@"; r=$?
|
||||
if [ $r -eq 0 ]; then
|
||||
git push --tags "$@"; r=$?
|
||||
fi
|
||||
return $r
|
||||
elif [ -n "$all_branches" ]; then
|
||||
# On a demandé à pusher toutes les branches
|
||||
git push --all "$@"
|
||||
return $?
|
||||
elif [ -n "$all_tags" ]; then
|
||||
# On a demandé à pusher tous les tags
|
||||
git push --tags "$@"
|
||||
return $?
|
||||
elif [ $# -gt 0 ]; then
|
||||
# Sinon, si des arguments sont spécifiés, les passer à git sans
|
||||
# modification
|
||||
git push "$@"
|
||||
return $?
|
||||
elif git_have_annex; then
|
||||
# Si une annexe existe dans le dépôt, demander à git-annex de faire la
|
||||
# synchronisation, sauf si --no-annex est spécifié ou si on est en mode
|
||||
# automatique
|
||||
if [ -z "$no_annex" -a -z "$auto" ]; then
|
||||
git annex sync
|
||||
return $?
|
||||
fi
|
||||
fi
|
||||
|
||||
# sinon on push vers origin. vérifier la présence du remote
|
||||
[ -n "$(git config --get remote.origin.url)" ] || {
|
||||
if [ -n "$auto" ]; then
|
||||
# en mode automatique, ignorer l'absence de remote
|
||||
return 0
|
||||
else
|
||||
eerror "Aucun remote origin n'est défini"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# puis calculer la branche à pusher
|
||||
local branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
||||
local origin="$(git config --get "branch.$branch.remote")"
|
||||
if [ -n "$branch" -a "$origin" == origin ]; then
|
||||
if [ -n "$auto" ]; then
|
||||
# en mode automatique, ne pousser que la branche courante
|
||||
git push "$origin" "$branch" || return
|
||||
else
|
||||
# utiliser la configuration par défaut, qui est sous debian squeeze
|
||||
# de pousser toutes les branches
|
||||
git push || return
|
||||
fi
|
||||
elif [ -n "$force" ]; then
|
||||
# utiliser la configuration par défaut, qui est sous debian squeeze de
|
||||
# pousser toutes les branches
|
||||
git push || return
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function git__pclone() {
|
||||
estep "$1 --> $(ppath "$2")"
|
||||
mkdirof "$2" || return 1
|
||||
git clone "$1" "$2" || return 1
|
||||
if [ -z "$3" ]; then
|
||||
(
|
||||
cd "$2"
|
||||
if git_have_rbranch develop; then
|
||||
git checkout develop || exit 1
|
||||
fi
|
||||
) || return 1
|
||||
fi
|
||||
git_annex_initial "$2" || return 1
|
||||
}
|
||||
function git__gitolite_info() {
|
||||
local mode="$1" urlbase="$2" pattern="$3"
|
||||
case "$mode" in
|
||||
http) curl -fs "$urlbase/info${pattern:+"?$pattern"}";;
|
||||
ssh) ssh -q "$urlbase" info ${pattern:+"$pattern"} 2>/dev/null;;
|
||||
esac
|
||||
}
|
||||
function git__filter_repos() {
|
||||
lawk -v prefix="$1" '
|
||||
NR <= 2 { next }
|
||||
{
|
||||
# filtrer les projets qui ne sont pas encore créés
|
||||
if (substr($0, 5, 2) == " C") next
|
||||
repo = substr($0, 6)
|
||||
# filtrer les projets de type wildcard
|
||||
if (repo ~ /[\[\]\*]/) next
|
||||
# enlever le prefixe
|
||||
if (prefix != "" && substr(repo, 1, length(prefix)) != prefix) next
|
||||
print repo
|
||||
}'
|
||||
}
|
||||
|
||||
function: git_clone ""
|
||||
function git_clone() {
|
||||
no_clone=
|
||||
update=
|
||||
nodevelop=
|
||||
recursive=
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
-n,--no-clone no_clone=1 \
|
||||
-u,--update update=1 \
|
||||
-m,--master nodevelop=1 \
|
||||
-r,--recursive recursive=1 \
|
||||
@ args -- "$@" && set -- "${args[@]}" || edie "$args" || return
|
||||
|
||||
if [ -n "$recursive" ]; then
|
||||
repobase="$1"
|
||||
[ -n "$repobase" ] || edie "Vous devez spécifier l'url de base des dépôts à cloner" || return
|
||||
if [ "${repobase#http://}" != "$repobase" -o "${repobase#https://}" != "$repobase" ]; then
|
||||
# accès par http
|
||||
mode=http
|
||||
splitfsep "$repobase" :// scheme hostuserpath
|
||||
splitfsep "$hostuserpath" / host userpath
|
||||
splitfsep "$userpath" / user basepath
|
||||
[ -n "$host" -a -n "$user" ] || edie "Vous devez spécifier l'hôte e.g http://host/git/basepath" || return
|
||||
urlbase="$scheme://$host/$user"
|
||||
else
|
||||
# accès par ssh
|
||||
mode=ssh
|
||||
splitfsep "$repobase" : userhost basepath
|
||||
splituserhost "$userhost" user host
|
||||
[ -n "$user" ] || user=git
|
||||
[ -n "$host" ] || edie "Vous devez spécifier l'hôte" || return
|
||||
urlbase="$user@$host"
|
||||
fi
|
||||
basepath="${basepath%/}"
|
||||
destbase="${2:-.}"
|
||||
|
||||
git_annex_use_ssh_wrapper
|
||||
prefix="${basepath:+$basepath/}"
|
||||
base_array_splitl repos "$(set -o pipefail; git__gitolite_info "$mode" "$urlbase" "$prefix" | git__filter_repos "$prefix")" || edie || return
|
||||
for repo in "${repos[@]}"; do
|
||||
case "$mode" in
|
||||
http) repourl="$urlbase/$repo";;
|
||||
ssh) repourl="$urlbase:$repo";;
|
||||
esac
|
||||
setx destdir=abspath "$destbase/${repo#$prefix}"
|
||||
if [ -d "$destdir" ]; then
|
||||
if [ -n "$update" ]; then
|
||||
(
|
||||
${no_clone:+qvals} cd "$destdir"
|
||||
${no_clone:+qvals} git pull
|
||||
) || edie || return
|
||||
else
|
||||
estepe "$(ppath2 "$destdir"): répertoire existant"
|
||||
fi
|
||||
elif [ -n "$no_clone" ]; then
|
||||
qvals git clone "$repourl" "$destdir"
|
||||
else
|
||||
git__pclone "$repourl" "$destdir" "$nodevelop" || edie || return
|
||||
fi
|
||||
done
|
||||
|
||||
else
|
||||
repourl="${1%.git}"
|
||||
[ -n "$repourl" ] || edie "Vous devez spécifier l'url du dépôt git" || return
|
||||
|
||||
destdir="$2"
|
||||
if [ -z "$destdir" ]; then
|
||||
splitfsep "$repourl" : userhost path
|
||||
setx destdir=basename -- "$path"
|
||||
destdir="${destdir%.git}"
|
||||
fi
|
||||
setx destdir=abspath "$destdir"
|
||||
|
||||
git_annex_use_ssh_wrapper
|
||||
if [ -d "$destdir" ]; then
|
||||
if [ -n "$update" ]; then
|
||||
(
|
||||
${no_clone:+qvals} cd "$destdir"
|
||||
${no_clone:+qvals} git pull
|
||||
) || edie || return
|
||||
else
|
||||
estepe "$(ppath2 "$destdir"): répertoire existant"
|
||||
fi
|
||||
elif [ -n "$no_clone" ]; then
|
||||
qvals git clone "$repourl" "$destdir"
|
||||
else
|
||||
git__pclone "$repourl" "$destdir" "$nodevelop" || edie || return
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function: git_crone ""
|
||||
function git_crone() {
|
||||
repourl="${1%.git}"
|
||||
[ -n "$repourl" ] || edie "Vous devez spécifier l'url du dépôt git" || return
|
||||
if [ "${repourl#http://}" != "$repourl" -o "${repourl#https://}" != "$repourl" ]; then
|
||||
# accès par http
|
||||
mode=http
|
||||
splitfsep "$repourl" :// scheme hostuserpath
|
||||
splitfsep "$hostuserpath" / host userpath
|
||||
splitfsep "$userpath" / user path
|
||||
[ -n "$host" -a -n "$user" ] || edie "Vous devez spécifier l'hôte e.g http://host/git/repo" || return
|
||||
hostuser="$scheme://$host/$user"
|
||||
else
|
||||
# accès par ssh
|
||||
mode=ssh
|
||||
splitfsep "$repourl" : userhost path
|
||||
splituserhost "$userhost" user host
|
||||
[ -n "$user" ] || user=git
|
||||
[ -n "$host" ] || edie "Vous devez spécifier l'hôte" || return
|
||||
userhost="$user@$host"
|
||||
fi
|
||||
[ -n "$path" ] || edie "Vous devez spécifier le chemin du dépôt git" || return
|
||||
|
||||
destdir="$2"
|
||||
if [ -z "$destdir" ]; then
|
||||
setx destdir=basename -- "$path"
|
||||
destdir="${destdir%.git}"
|
||||
fi
|
||||
tmpdestdir=
|
||||
if [ -d "$destdir" ]; then
|
||||
[ -d "$destdir/.git" ] && edie "$(ppath2 "$destdir"): un dépôt existe déjà" || return
|
||||
ac_set_tmpdir tmpdestdir
|
||||
fi
|
||||
|
||||
if [ "$mode" == http ]; then
|
||||
setx result=curl -fs "$hostuser/create?$path" || edie || return
|
||||
echo "$result"
|
||||
[[ "$result" == FATAL:* ]] && edie || return
|
||||
if [ -n "$tmpdestdir" ]; then
|
||||
setxx destname=abspath "$destdir" // basename
|
||||
git clone "$hostuser/$path" "$tmpdestdir/$destname" || edie || return
|
||||
mv "$tmpdestdir/$destname/.git" "$destdir" || edie || return
|
||||
ac_clean "$tmpdestdir"
|
||||
else
|
||||
git clone "$hostuser/$path" "$destdir" || edie || return
|
||||
fi
|
||||
elif [ "$mode" == ssh ]; then
|
||||
git_annex_use_ssh_wrapper
|
||||
ssh "$userhost" create "$path" || edie || return
|
||||
if [ -n "$tmpdestdir" ]; then
|
||||
setxx destname=abspath "$destdir" // basename
|
||||
git clone "$userhost:$path" "$tmpdestdir/$destname" || edie || return
|
||||
mv "$tmpdestdir/$destname/.git" "$destdir" || edie || return
|
||||
ac_clean "$tmpdestdir"
|
||||
else
|
||||
git clone "$userhost:$path" "$destdir" || edie || return
|
||||
fi
|
||||
else
|
||||
edie "$mode: mode non supporté" || return
|
||||
fi
|
||||
git_annex_initial "$destdir" || edie || return
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
../load.sh
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: pretty "Affichage en couleur"
|
||||
require: base
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
##@cooked nocomments
|
||||
module: sysinfos "Informations sur le système courant"
|
||||
require: base
|
|
@ -0,0 +1,2 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
__uaddpath "@@dest@@/bin" PATH
|
|
@ -0,0 +1,9 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
source "$@" || exit 1
|
||||
source "$ULIBDIR/ulib" || exit 1
|
||||
urequire DEFAULTS
|
||||
cd "$scriptdir/../.."
|
||||
|
||||
# supprimer les fichiers de VCS
|
||||
rm -rf .git
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
source "$@" || exit 1
|
||||
source "$ULIBDIR/ulib" || exit 1
|
||||
urequire DEFAULTS
|
||||
cd "$scriptdir/../.."
|
||||
|
||||
sed "s|@@""dest""@@|$dest|g" load.sh >/etc/nucore.sh
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,159 @@
|
|||
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
## Charger nucore et rendre disponible les modules bash, awk, php et python
|
||||
##@cooked nocomments
|
||||
# Ce fichier doit être sourcé en premier. Si ce fichier n'est pas sourcé, alors
|
||||
# le répertoire nucore doit être disponible dans le répertoire du script qui
|
||||
# inclue ce fichier.
|
||||
# Une fois ce fichier sourcé, les autres modules peuvent être importés avec
|
||||
# require:() e.g.
|
||||
# source /etc/nucore.sh || exit 1
|
||||
# require: other_modules
|
||||
# ou pour une copie locale de nucore:
|
||||
# source "$(dirname "$0")/nucore/load.sh" || exit 1
|
||||
# require: other_modules
|
||||
|
||||
# vérifier version minimum de bash
|
||||
if [ "x$BASH" = "x" ]; then
|
||||
echo "ERROR: nucore: this script requires bash"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function eerror() { echo "ERROR: $*" 1>&2; }
|
||||
function die() { [ $# -gt 0 ] && eerror "$*"; exit 1; }
|
||||
function edie() { [ $# -gt 0 ] && eerror "$*"; return 1; }
|
||||
function delpath() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; ${2:-PATH}"'="${'"${2:-PATH}"'#$1:}"; '"${2:-PATH}"'="${'"${2:-PATH}"'%:$1}"; '"${2:-PATH}"'="${'"${2:-PATH}"'//:$_qdir:/:}"; [ "$'"${2:-PATH}"'" == "$1" ] && '"${2:-PATH}"'='; }
|
||||
function addpath() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="${'"${2:-PATH}"':+$'"${2:-PATH}"':}$1"'; }
|
||||
function inspathm() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="$1${'"${2:-PATH}"':+:$'"${2:-PATH}"'}"'; }
|
||||
function inspath() { delpath "$@"; inspathm "$@"; }
|
||||
|
||||
if [ ${BASH_VERSINFO[0]} -ge 5 -o \( ${BASH_VERSINFO[0]} -eq 4 -a ${BASH_VERSINFO[1]} -ge 1 \) ]; then :
|
||||
elif [ -n "$NUCORE_IGNORE_BASH_VERSION" ]; then :
|
||||
else die "nucore: bash 4.1+ is required"
|
||||
fi
|
||||
|
||||
# Calculer emplacement de nucore
|
||||
NUCOREDIR="@@dest@@"
|
||||
if [ "$NUCOREDIR" = "@@""dest""@@" ]; then
|
||||
# La valeur "@@"dest"@@" n'est remplacée que dans la copie de ce script
|
||||
# faite dans /etc. Sinon, il faut toujours faire le calcul. Cela permet de
|
||||
# déplacer la librairie n'importe où sur le disque, ce qui est
|
||||
# particulièrement intéressant quand on fait du déploiement.
|
||||
NUCOREDIR="${BASH_SOURCE[0]}"
|
||||
if [ -f "$NUCOREDIR" -a "$(basename -- "$NUCOREDIR")" == load.sh ]; then
|
||||
# Fichier sourcé depuis nucore/
|
||||
NUCORE_SOURCED=1
|
||||
NUCOREDIR="$(dirname -- "$NUCOREDIR")"
|
||||
elif [ -f "$NUCOREDIR" -a "$(basename -- "$NUCOREDIR")" == nucore.sh ]; then
|
||||
# Fichier sourcé depuis nucore/bash
|
||||
NUCORE_SOURCED=1
|
||||
NUCOREDIR="$(dirname -- "$NUCOREDIR")/.."
|
||||
else
|
||||
# Fichier non sourcé. Tout exprimer par rapport au script courant
|
||||
NUCORE_SOURCED=
|
||||
NUCOREDIR="$(dirname -- "$0")"
|
||||
if [ -d "$NUCOREDIR/nucore" ]; then
|
||||
NUCOREDIR="$NUCOREDIR/nucore"
|
||||
elif [ -d "$NUCOREDIR/lib/nucore" ]; then
|
||||
NUCOREDIR="$NUCOREDIR/lib/nucore"
|
||||
fi
|
||||
fi
|
||||
elif [ "${BASH_SOURCE[0]}" = /etc/nucore.sh ]; then
|
||||
# Fichier chargé depuis /etc/nucore.sh
|
||||
NUCORE_SOURCED=1
|
||||
fi
|
||||
NUCOREDIR="$(cd "$NUCOREDIR" 2>/dev/null; pwd)"
|
||||
NUCOREDIRS=("$NUCOREDIR/bash")
|
||||
|
||||
# marqueur pour vérifier que nucore a réellement été chargé. il faut avoir $NUCOREINIT == $NUCOREDIR
|
||||
# utilisé par le module base qui doit pouvoir être inclus indépendamment
|
||||
NUCOREINIT="$NUCOREDIR"
|
||||
|
||||
## Modules bash
|
||||
NUCORE_LOADED_MODULES=(nucore)
|
||||
NUCORE_DEFAULT_MODULES=(base pretty sysinfos)
|
||||
|
||||
# Si cette variable est non vide, require: recharge toujours le module, même
|
||||
# s'il a déjà été chargé. Cette valeur n'est pas transitive: il faut toujours
|
||||
# recharger explicitement tous les modules désirés
|
||||
NUCORE_FORCE_RELOAD=
|
||||
|
||||
function nucore__define_functions() {
|
||||
function nucore_check_loaded() {
|
||||
local module
|
||||
for module in "${NUCORE_LOADED_MODULES[@]}"; do
|
||||
[ "$module" == "$1" ] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
function module:() {
|
||||
NUCORE_MODULE="$1"
|
||||
if ! nucore_check_loaded "$1"; then
|
||||
NUCORE_LOADED_MODULES+=("$1")
|
||||
fi
|
||||
}
|
||||
function function:() {
|
||||
:
|
||||
}
|
||||
}
|
||||
|
||||
function nucore__require:() {
|
||||
local nr__module nr__nucoredir nr__found
|
||||
[ $# -gt 0 ] || set DEFAULTS
|
||||
|
||||
# sauvegarder valeurs globales
|
||||
local nr__orig_module="$NUCORE_MODULE"
|
||||
NUCORE_MODULE=
|
||||
|
||||
# garder une copie de la valeur originale et casser la transitivité
|
||||
local nr__force_reload="$NUCORE_FORCE_RELOAD"
|
||||
local NUCORE_FORCE_RELOAD
|
||||
|
||||
for nr__module in "$@"; do
|
||||
nr__found=
|
||||
for nr__nucoredir in "${NUCOREDIRS[@]}"; do
|
||||
if [ -f "$nr__nucoredir/$nr__module.sh" ]; then
|
||||
nr__found=1
|
||||
if [ -n "$nr__force_reload" ] || ! nucore_check_loaded "$nr__module"; then
|
||||
NUCORE_LOADED_MODULES+=("$nr__module")
|
||||
source "$nr__nucoredir/$nr__module.sh" || die
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$nr__found" -a "$nr__module" == DEFAULTS ]; then
|
||||
for nr__module in "${NUCORE_DEFAULT_MODULES[@]}"; do
|
||||
if [ -f "$nr__nucoredir/$nr__module.sh" ]; then
|
||||
nr__found=1
|
||||
if [ -n "$nr__force_reload" ] || ! nucore_check_loaded "$nr__module"; then
|
||||
NUCORE_LOADED_MODULES+=("$nr__module")
|
||||
source "$nr__nucoredir/$nr__module.sh" || die
|
||||
fi
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[ -n "$nr__found" ] || die "nucore: unable to find module $nr__module in (${NUCOREDIRS[*]})"
|
||||
done
|
||||
|
||||
# restaurer valeurs globales
|
||||
NUCORE_MODULE="$nr__orig_module"
|
||||
}
|
||||
|
||||
function require:() {
|
||||
[ -z "$NUCORE_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local NUCORE_REQUIRE_SET_X=1; }; if [ -n "$NUCORE_REQUIRE_SET_X" ]; then [ -n "$NUCORE_REQUIRE_SET_X_RL1" ] || local NUCORE_REQUIRE_SET_X_RL1; local NUCORE_REQUIRE_SET_X_RL2=$RANDOM; [ -n "$NUCORE_REQUIRE_SET_X_RL1" ] || NUCORE_REQUIRE_SET_X_RL1=$NUCORE_REQUIRE_SET_X_RL2; fi # désactiver set -x de manière réentrante
|
||||
nucore__define_functions
|
||||
nucore__require: "$@"
|
||||
[ -n "$NUCORE_REQUIRE_SET_X" -a "$NUCORE_REQUIRE_SET_X_RL1" == "$NUCORE_REQUIRE_SET_X_RL2" ] && set -x
|
||||
return 0
|
||||
}
|
||||
|
||||
## Autres modules
|
||||
[ -d "$NUCOREDIR/awk" ] && inspath "$NUCOREDIR/awk" AWKPATH; export AWKPATH
|
||||
[ -d "$NUCOREDIR/python3" ] && inspath "$NUCOREDIR/python3" PYTHONPATH; export PYTHONPATH
|
||||
|
||||
## Auto import DEFAULTS
|
||||
nucore__define_functions
|
||||
if [ -n "$NUCORE_SOURCED" -a -z "$NUCORE_NO_IMPORT_DEFAULTS" ]; then
|
||||
require: DEFAULTS
|
||||
fi
|
Loading…
Reference in New Issue