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