548 lines
19 KiB
Bash
548 lines
19 KiB
Bash
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
## Gestion des modules pour runs
|
|
##@cooked nocomments
|
|
##@require base
|
|
uprovide runsmod
|
|
urequire base
|
|
|
|
function __runsmod_loadconf() {
|
|
# Charger le fichier de configuration $1. Les paramètres RUNSMOD_MODE,
|
|
# RUNSMOD_SHALLOW et RUNSMOD_UPDATE peuvent être modifiés par rapport à la
|
|
# configuration chargée avec les paramètres $2, $3 et $4 respectivement.
|
|
local config="$1" mode="$2" shallow="$3" update="$4"
|
|
|
|
urequire runsmod.defaults
|
|
set_defaults runsmod
|
|
if [ -n "$config" ]; then
|
|
[ -f "$config" ] || {
|
|
eerror "$config: fichier introuvable"
|
|
return 1
|
|
}
|
|
source "$config" || {
|
|
eerror "Erreur de configuration"
|
|
return 1
|
|
}
|
|
fi
|
|
|
|
[ -n "$mode" -a "$mode" != --NOT-SET-- ] || mode="$RUNSMOD_MODE"
|
|
case "$mode" in
|
|
production|prod|p) mode=prod;;
|
|
development|devel|dev|d) mode=devel;;
|
|
*) die "$mode: mode invalide. Ce doit être prod ou devel";;
|
|
esac
|
|
RUNSMOD_MODE="$mode"
|
|
|
|
[ -n "$shallow" -a "$shallow" != --NOT-SET-- ] || shallow="$RUNSMOD_SHALLOW"
|
|
if [ "$shallow" == auto ]; then
|
|
case "$RUNSMOD_MODE" in
|
|
prod) shallow=1;;
|
|
devel) shallow=;;
|
|
esac
|
|
fi
|
|
normyesval shallow
|
|
RUNSMOD_SHALLOW="$shallow"
|
|
|
|
[ -n "$update" -a "$update" != --NOT-SET-- ] || update="$RUNSMOD_UPDATE"
|
|
if [ "$update" == auto ]; then
|
|
case "$RUNSMOD_MODE" in
|
|
prod) update=pull;;
|
|
devel) update=clone;;
|
|
esac
|
|
fi
|
|
RUNSMOD_UPDATE="$update"
|
|
case "$RUNSMOD_UPDATE" in
|
|
offline) RUNSMOD_CLONE=; RUNSMOD_PULL=;;
|
|
clone) RUNSMOD_CLONE=1; RUNSMOD_PULL=;;
|
|
pull) RUNSMOD_CLONE=1; RUNSMOD_PULL=1;;
|
|
esac
|
|
|
|
return 0
|
|
}
|
|
|
|
function __runsmod_get() {
|
|
# obtenir la valeur de la première variable définie dans une liste
|
|
# construite à partir des arguments de cette fonction.
|
|
# $1 étant le suffixe, pour chacun des préfixes $2..@, tester l'existence de
|
|
# la variable "RUNSMOD_${prefix}_${suffix}". Le cas particulier prefix==""
|
|
# teste l'existence de la variable RUNSMOD_${suffix}
|
|
# Si la liste des préfixes n'est pas spécifiée, prendre par défaut la liste
|
|
# suivante: ("${RUNSMOD_PROFILE}_${RUNSMOD_MODE}" "$RUNSMOD_PROFILE" "")
|
|
|
|
# Si $1=-a, alors copier un tableau plutôt qu'afficher une valeur
|
|
# scalaire. dans ce cas, $2 est le nom du tableau destination, et toutes les
|
|
# autres valeurs indiquées ci-dessus sont décalées de 2 vers la droite
|
|
local _array
|
|
if [ "$1" == -a ]; then
|
|
_array="$2"
|
|
shift; shift
|
|
fi
|
|
local _suffix="$1"; shift
|
|
[ -n "$_suffix" ] || return 1
|
|
|
|
if [ $# -eq 0 ]; then
|
|
# préfixes par défaut
|
|
local -a _args
|
|
if [ -n "$RUNSMOD_PROFILE" ]; then
|
|
if [ -n "$RUNSMOD_MODE" ]; then
|
|
_args=("${_args[@]}" "${RUNSMOD_PROFILE}_${RUNSMOD_MODE}")
|
|
fi
|
|
_args=("${_args[@]}" "$RUNSMOD_PROFILE")
|
|
fi
|
|
_args=("${_args[@]}" "")
|
|
set -- "${_args[@]}"
|
|
fi
|
|
local _prefix _var
|
|
local -a _values
|
|
for _prefix in "$@"; do
|
|
if [ -n "$_prefix" ]; then
|
|
_var="RUNSMOD_${_prefix}_${_suffix}"
|
|
else
|
|
_var="RUNSMOD_${_suffix}"
|
|
fi
|
|
if [ -n "$_array" ]; then
|
|
array_copy _values "$_var"
|
|
if [ ${#_values[*]} -gt 0 -a -n "${_values[0]}" ]; then
|
|
array_copy "$_array" "$_var"
|
|
return 0
|
|
fi
|
|
else
|
|
_var="${!_var}"
|
|
if [ -n "$_var" ]; then
|
|
echo "$_var"
|
|
return 0
|
|
fi
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
function __runsmod_fixurl() {
|
|
# Ajouter la définition de dépôt $1 à l'url de base $2 pour en faire un url
|
|
# de dépot.
|
|
local url="$2"
|
|
case "$url" in
|
|
http:*|https:*)
|
|
[ "${url%/}" != "$url" ] || url="$url/"
|
|
;;
|
|
*)
|
|
if [[ "$url" == *: ]]; then
|
|
:
|
|
elif [[ "$url" == *:* ]]; then
|
|
[ "${url%/}" != "$url" ] || url="$url/"
|
|
else
|
|
url="$url:"
|
|
fi
|
|
;;
|
|
esac
|
|
echo "$url$1"
|
|
}
|
|
|
|
function __runsmod_getpath_from_baseurl() {
|
|
# obtenir le nom correspond à un url de base, utilisable dans un chemin
|
|
local url="$1" scheme path userhost user host dummy
|
|
case "$url" in
|
|
http:*|https:*)
|
|
scheme="${url%%:*}"
|
|
path="${url#*://}"
|
|
path="${path%/}"
|
|
path="${path/:\/\//_}"
|
|
path="${path//\//_}"
|
|
echo "${path}_${scheme}"
|
|
return
|
|
;;
|
|
*)
|
|
splitpair "$url" userhost dummy
|
|
splituserhost "$userhost" user host
|
|
echo "${host}_${user}_ssh"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
__RUNSMOD_CONNECT_TIMEOUT=3
|
|
|
|
function __runsmod_dumpurl() {
|
|
if progexists curl; then
|
|
curl -fs --connect-timeout "$__RUNSMOD_CONNECT_TIMEOUT" "$@"
|
|
elif progexists wget; then
|
|
wget -q --connect-timeout "$__RUNSMOD_CONNECT_TIMEOUT" -O - "$@"
|
|
else
|
|
eerror "Nécessite curl ou wget"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function __runsmod_getinfo() {
|
|
# interroger le serveur gitolite à l'url de base $1 avec la commande info
|
|
local url="$1"
|
|
case "$url" in
|
|
http:*|https:*)
|
|
__runsmod_dumpurl "${url%/}/info"
|
|
;;
|
|
*)
|
|
local userhost dummy
|
|
splitpair "$url" userhost dummy
|
|
local -a options
|
|
options=(
|
|
-o StrictHostKeyChecking=no
|
|
-o BatchMode=yes
|
|
-o ConnectTimeout="$__RUNSMOD_CONNECT_TIMEOUT"
|
|
)
|
|
"${GIT_SSH:-ssh}" -q "${options[@]}" "$userhost" info
|
|
;;
|
|
esac
|
|
}
|
|
function __runsmod_fixinfo() {
|
|
# traiter le résultat de __runsmod_getinfo() pour avoir la liste des dépôts
|
|
sed -n '3,$p' | sed 's/^.*\t//g'
|
|
}
|
|
|
|
function runsmod_checkenv() {
|
|
# vérifier l'environement. créer les répertoires nécessaires.
|
|
if [ -z "$RUNSMOD_BASEDIR" ]; then
|
|
eerror "Vous devez définir RUNSMOD_BASEDIR"
|
|
return 1
|
|
fi
|
|
if [ ! -d "$RUNSMOD_BASEDIR" ]; then
|
|
estep "Création de $(ppath "$RUNSMOD_BASEDIR")"
|
|
mkdir -p "$RUNSMOD_BASEDIR" || return 1
|
|
fi
|
|
}
|
|
|
|
function __runsmod_get_repolistfile() {
|
|
# obtenir le chemin absolu vers le fichier contenant la liste des dépôts
|
|
# correspondant à l'url de base $1
|
|
local repopath
|
|
setx repopath=__runsmod_getpath_from_baseurl "$1"
|
|
echo "$RUNSMOD_BASEDIR/info-$repopath.lst"
|
|
}
|
|
|
|
function runsmod_should_update_repolists() {
|
|
# tester s'il faut mettre à jour au moins un des fichiers contenant les
|
|
# listes des dépôts
|
|
local RUNSMOD_PROFILE
|
|
local now baseurl repobase repopath repolistfile mtime
|
|
local -a urls
|
|
setx now=date +%s
|
|
for RUNSMOD_PROFILE in "${RUNSMOD_PROFILES[@]}"; do
|
|
setx baseurl=__runsmod_get BASEURL || continue
|
|
setx repolistfile=__runsmod_get_repolistfile "$baseurl"
|
|
|
|
# si le fichier n'existe pas, il faut mettre à jour
|
|
[ -f "$repolistfile" ] || return 0
|
|
# si le fichier a été modifié depuis plus de 24 heures, mettre à jour
|
|
setx mtime=stat -c %Y "$repolistfile"
|
|
[ $(($now - $mtime)) -lt 86400 ] || return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
function runsmod_update_repolists() {
|
|
# mettre à jour si nécessaire les fichiers contenant les listes des dépôts.
|
|
# Si $1 n'est pas vide, forcer la mise à jour de tous les fichiers
|
|
local force="$1"; shift
|
|
local RUNSMOD_PROFILE
|
|
local now baseurl repobase repopath repo mtime update
|
|
local -a urls
|
|
setx now=date +%s
|
|
for RUNSMOD_PROFILE in "${RUNSMOD_PROFILES[@]}"; do
|
|
setx baseurl=__runsmod_get BASEURL || continue
|
|
setx repolistfile=__runsmod_get_repolistfile "$baseurl"
|
|
|
|
update="$force"
|
|
if [ -z "$update" ]; then
|
|
# si le fichier n'existe pas, il faut mettre à jour
|
|
[ -f "$repolistfile" ] || update=1
|
|
fi
|
|
if [ -z "$update" ]; then
|
|
# si le fichier a été modifié depuis plus de 24 heures, mettre à jour
|
|
setx mtime=stat -c %Y "$repolistfile"
|
|
[ $(($now - $mtime)) -lt 86400 ] || update=1
|
|
fi
|
|
if [ -n "$update" ]; then
|
|
local list
|
|
ebegin "$baseurl"
|
|
if setx list=__runsmod_getinfo "$baseurl"; then
|
|
echo "$list" | __runsmod_fixinfo >"$repolistfile"
|
|
edot 0
|
|
else
|
|
edot 1
|
|
fi
|
|
eend
|
|
fi
|
|
done
|
|
}
|
|
|
|
function runsmod_setup_vars() {
|
|
# récupérer configuration statique pour la mettre à jour
|
|
array_new REPODIRS
|
|
array_split SCRIPTSDIRS "$RUNSSCRIPTSPATH" :
|
|
array_split MODULESDIRS "$RUNSMODULESPATH" :
|
|
array_split HOSTSDIRS "$RUNSHOSTSPATH" :
|
|
}
|
|
|
|
function __runsmod_has_vmodule() {
|
|
# tester si l'url $1 contient une variable de module %m
|
|
[ "${1//%m/}" != "$1" ]
|
|
}
|
|
function __runsmod_has_vhost() {
|
|
# tester si l'url $1 contient une variable d'hôte %h
|
|
[ "${1//%h/}" != "$1" ]
|
|
}
|
|
function __runsmod_replace1() {
|
|
# remplacer dans l'url $1 la variable %h par l'hôte complet $2 et
|
|
# éventuellement la variable %m par le module $3
|
|
local url="$1"
|
|
[ -n "$2" ] && url="${url//%h/$2}"
|
|
[ -n "$3" ] && url="${url//%m/$3}"
|
|
echo "$url"
|
|
}
|
|
function __runsmod_replace2() {
|
|
# remplacer dans l'url $1 la variable %h par le nom d'hôte correspondant à
|
|
# au nom d'hôte complet $2 et éventuellement la variable %m par le module $3
|
|
local url="$1"
|
|
local host="${2%%.*}"
|
|
[ -n "$host" ] && url="${url//%h/$host}"
|
|
[ -n "$3" ] && url="${url//%m/$3}"
|
|
echo "$url"
|
|
}
|
|
function __runsmod_match() {
|
|
# vérifier que $2 correspond au pattern $1
|
|
eval "[[ $(qval "$2") == $(qwc "$1") ]]"
|
|
}
|
|
function __runsmod_match_repo_add() {
|
|
# vérifier qu'un dépôt de pattern $2 se trouve dans la liste de dépôt $1
|
|
# si c'est le cas, rajouter le dépôt dans le tableau $3 le cas échéant
|
|
local __rs="$1[@]" __r __found
|
|
for __r in "${!__rs}"; do
|
|
if [[ "$__r" == *\** ]]; then
|
|
: # ignore les dépôts wildcard
|
|
elif __runsmod_match "$2" "$__r"; then
|
|
[ -n "$3" ] && array_add "$3" "$__r"
|
|
__found=1
|
|
fi
|
|
done
|
|
[ -n "$__found" ]
|
|
}
|
|
|
|
function __runsmod_clone_or_pull() {
|
|
local repourl="$1" repodir="$2"
|
|
mkdirof "$repodir"
|
|
if [ -d "$repodir" ]; then
|
|
if [ -n "$RUNSMOD_PULL" ]; then
|
|
estepi "pull $(ppath "$repodir") [$repourl]"
|
|
(cd "$repodir"; git pull)
|
|
return $?
|
|
else
|
|
estep "nopull $(ppath "$repodir")"
|
|
return 0
|
|
fi
|
|
else
|
|
if [ -n "$RUNSMOD_CLONE" ]; then
|
|
estepi "clone $(ppath "$repodir") [$repourl]"
|
|
git clone ${RUNSMOD_SHALLOW:+--depth 1} "$repourl" "$repodir"
|
|
return $?
|
|
else
|
|
estepe "noclone $(ppath "$repodir")"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function runsmod_clone_or_pull() {
|
|
# Chercher les modules $3..@, pour l'hôte $1 qui est le mode d'hôte: none,
|
|
# all, self ou one pour un hôte spécifique $2. Ajouter les chemins dans le
|
|
# tableau REPO_DIRS. Mettre à jour les tableaux SCRIPTS_DIRS, MODULES_DIRS
|
|
# et HOSTS_DIRS
|
|
local all_hosts host_mode="$1" host="$2"; shift; shift
|
|
case "$host_mode" in
|
|
none) host=;;
|
|
all) host=; all_hosts=1;;
|
|
self) host="${RUNSHOST:-$MYHOST}";;
|
|
esac
|
|
if [ -n "$host" -a "${host%%.*}" == "$host" -a -n "$RUNSDOMAIN" ]; then
|
|
# le nom d'hôte doit être avec un domaine
|
|
host="$host.$RUNSDOMAIN"
|
|
enote "Autocorrection du nom d'hôte en $host"
|
|
fi
|
|
#XXX implémenter all_hosts=1
|
|
|
|
local -a repolist reponames repourls
|
|
local RUNSMOD_PROFILE baseurl repopath repolistfile
|
|
local vprefix repospec reposuffix reponame repourl repodir module moduledir
|
|
local r=0
|
|
|
|
# Tout d'abord, traiter les dépôts sans variable %m
|
|
edebug "Traitement des dépôts sans vmodule"
|
|
for RUNSMOD_PROFILE in "${RUNSMOD_PROFILES[@]}"; do
|
|
setx baseurl=__runsmod_get BASEURL || continue
|
|
setx repopath=__runsmod_getpath_from_baseurl "$baseurl"
|
|
setx repolistfile=__runsmod_get_repolistfile "$baseurl"
|
|
[ -f "$repolistfile" ] || continue
|
|
array_from_lines repolist "$(<"$repolistfile")"
|
|
|
|
edebug ".. baseurl=$baseurl, repopath=$repopath"
|
|
for vprefix in SCRIPTS MODULES HOSTS; do
|
|
__runsmod_get -a repourls "${vprefix}_URLS"
|
|
edebug ".... vprefix=$vprefix, repourls=(${repourls[*]})"
|
|
|
|
for repospec in "${repourls[@]}"; do
|
|
edebug "...... repospec=$repospec"
|
|
__runsmod_has_vmodule "$repospec" && continue
|
|
if [[ "$repospec" == *//* ]]; then
|
|
reposuffix="${repospec#*//}"
|
|
[ -n "$reposuffix" ] && reposuffix="/$reposuffix"
|
|
repospec="${repospec%%//*}"
|
|
else
|
|
reposuffix=
|
|
fi
|
|
|
|
reponames=()
|
|
if __runsmod_has_vhost "$repospec"; then
|
|
if [ -n "$all_hosts" ]; then
|
|
setx repospec=__runsmod_replace1 "$repospec" "*"
|
|
__runsmod_match_repo_add repolist "$repospec" reponames
|
|
elif [ -n "$host" ]; then
|
|
setx reponame=__runsmod_replace1 "$repospec" "$host"
|
|
array_contains repolist "$reponame" && array_add reponames "$reponame"
|
|
setx reponame=__runsmod_replace2 "$repospec" "$host"
|
|
array_contains repolist "$reponame" && array_add reponames "$reponame"
|
|
fi
|
|
else
|
|
array_contains repolist "$repospec" && array_add reponames "$repospec"
|
|
fi
|
|
|
|
edebug "...... reponames=(${reponames[*]})"
|
|
for reponame in "${reponames[@]}"; do
|
|
repodir="$RUNSMOD_BASEDIR/$repopath/$reponame"
|
|
|
|
setx repourl=__runsmod_fixurl "$reponame" "$baseurl"
|
|
__runsmod_clone_or_pull "$repourl" "$repodir" || r=1
|
|
|
|
[ -d "$repodir" ] || continue
|
|
array_contains REPODIRS "$repodir" && continue
|
|
array_addu REPODIRS "$repodir"
|
|
|
|
repodir="$repodir$reposuffix"
|
|
case "$vprefix" in
|
|
SCRIPTS) array_addu SCRIPTSDIRS "$repodir";;
|
|
MODULES) array_addu MODULESDIRS "$repodir";;
|
|
HOSTS) array_addu HOSTSDIRS "$repodir";;
|
|
esac
|
|
done
|
|
done
|
|
done
|
|
done
|
|
|
|
## Ensuite, traiter les dépôts de module
|
|
|
|
# modules contient la liste des modules qui ont été trouvés, pour ne pas les
|
|
# lister en double s'ils existent dans plusieurs sources
|
|
edebug "Traitement des dépôts de modules"
|
|
local -a modules foundmodules
|
|
local all_modules
|
|
|
|
modules=("$@")
|
|
for RUNSMOD_PROFILE in "${RUNSMOD_PROFILES[@]}"; do
|
|
setx baseurl=__runsmod_get BASEURL || continue
|
|
setx repopath=__runsmod_getpath_from_baseurl "$baseurl"
|
|
setx repolistfile=__runsmod_get_repolistfile "$baseurl"
|
|
[ -f "$repolistfile" ] || continue
|
|
array_from_lines repolist "$(<"$repolistfile")"
|
|
|
|
edebug ".. baseurl=$baseurl, repopath=$repopath"
|
|
for module in "${modules[@]}"; do
|
|
if [ "$module" == "*" ]; then
|
|
module=
|
|
all_modules=1
|
|
else
|
|
array_contains foundmodules "$module" && continue
|
|
all_modules=
|
|
fi
|
|
edebug ".... module=$module"
|
|
|
|
for vprefix in SCRIPTS MODULES HOSTS; do
|
|
__runsmod_get -a repourls "${vprefix}_URLS"
|
|
edebug "...... vprefix=$vprefix, repourls=(${repourls[*]})"
|
|
|
|
for repospec in "${repourls[@]}"; do
|
|
edebug "........ repospec=$repospec"
|
|
__runsmod_has_vmodule "$repospec" || continue
|
|
if [[ "$repospec" == *//* ]]; then
|
|
reposuffix="${repospec#*//}"
|
|
[ -n "$reposuffix" ] && reposuffix="/$reposuffix"
|
|
repospec="${repospec%%//*}"
|
|
else
|
|
reposuffix=
|
|
fi
|
|
|
|
reponames=()
|
|
if [ -n "$all_modules" ]; then
|
|
if __runsmod_has_vhost "$repospec"; then
|
|
if [ -n "$all_hosts" ]; then
|
|
setx repospec=__runsmod_replace1 "$repospec" "*" "*"
|
|
__runsmod_match_repo_add repolist "$repospec" reponames
|
|
elif [ -n "$host" ]; then
|
|
setx repospec=__runsmod_replace1 "$repospec" "$host" "*"
|
|
__runsmod_match_repo_add repolist "$repospec" reponames
|
|
setx repospec=__runsmod_replace2 "$repospec" "$host" "*"
|
|
__runsmod_match_repo_add repolist "$repospec" reponames
|
|
fi
|
|
else
|
|
setx repospec=__runsmod_replace1 "$repospec" "" "*"
|
|
__runsmod_match_repo_add repolist "$repospec" reponames
|
|
fi
|
|
else
|
|
if __runsmod_has_vhost "$repospec"; then
|
|
if [ -n "$host" ]; then
|
|
setx reponame=__runsmod_replace1 "$repospec" "$host" "$module"
|
|
array_contains repolist "$reponame" && array_add reponames "$reponame"
|
|
setx reponame=__runsmod_replace2 "$repospec" "$host" "$module"
|
|
array_contains repolist "$reponame" && array_add reponames "$reponame"
|
|
fi
|
|
else
|
|
setx reponame=__runsmod_replace1 "$repospec" "" "$module"
|
|
array_contains repolist "$reponame" && array_add reponames "$reponame"
|
|
fi
|
|
fi
|
|
|
|
edebug "........ reponames=(${reponames[*]})"
|
|
for reponame in "${reponames[@]}"; do
|
|
repodir="$RUNSMOD_BASEDIR/$repopath/$reponame"
|
|
|
|
setx repourl=__runsmod_fixurl "$reponame" "$baseurl"
|
|
__runsmod_clone_or_pull "$repourl" "$repodir" || r=1
|
|
|
|
[ -d "$repodir" ] || continue
|
|
array_contains REPODIRS "$repodir" && continue
|
|
array_addu REPODIRS "$repodir"
|
|
[ -z "$all_modules" ] && array_addu foundmodules "$module"
|
|
|
|
repodir="$repodir$reposuffix"
|
|
case "$vprefix" in
|
|
SCRIPTS) array_addu SCRIPTSDIRS "$repodir";;
|
|
MODULES)
|
|
setx moduledir=dirname -- "$repodir"
|
|
array_addu MODULESDIRS "$moduledir"
|
|
;;
|
|
HOSTS) array_addu HOSTSDIRS "$repodir";;
|
|
esac
|
|
done
|
|
done
|
|
done
|
|
done
|
|
done
|
|
|
|
for module in "${modules[@]}"; do
|
|
[ "$module" == "*" ] && continue
|
|
array_contains foundmodules "$module" || ewarn "$module: module non trouvé"
|
|
done
|
|
|
|
return $r
|
|
}
|
|
|
|
function runsmod_teardown_vars() {
|
|
setx RUNSSCRIPTSPATH=array_join SCRIPTSDIRS :
|
|
setx RUNSMODULESPATH=array_join MODULESDIRS :
|
|
setx RUNSHOSTSPATH=array_join HOSTSDIRS :
|
|
}
|