Intégration de la branche release-6.4.0
This commit is contained in:
		
						commit
						4f5d3794fe
					
				
							
								
								
									
										45
									
								
								CHANGES.md
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								CHANGES.md
									
									
									
									
									
								
							| @ -1,3 +1,48 @@ | ||||
| ## Version 6.4.0 du 05/05/2017-16:50 | ||||
| 
 | ||||
| * `c25160c` fndate: maj doc et améliorations ergonomiques | ||||
| * `d5f4ae2` pclone: filtrer les projets de type wildcard | ||||
| * `f8f731e` support de la complétion pour rwoinst -w | ||||
| * `e4b7714` tailor.py et chrono.py: améliorer l'affichage de l'aide | ||||
| * `6f1d5e5` Intégration de la branche rwoinst-updates | ||||
|   * `4aaded5` support des répertoires source maven et de l'interrogation de deploy pour: profil, déploiement des resources web, variables bounce, notag, exec, dbconfig, dbconfigmap | ||||
|   * `f20cc48` rwoinst: ajouter l'option -w qui peut être spécifiée en parallèle de -h pour déployer les resources web vers un serveur différent | ||||
|   * `9e4ccae` woinst: support des préfixes dans les variables | ||||
|   * `8f9ddb5` uinst.sh et woinst.sh: améliorer la comptabilité | ||||
|   * `e01cabb` makeself: retourner le code d'erreur même avec un auto-extractible temporaire | ||||
| * `8482d61` pclone: ajouter l'option --master | ||||
| * `a264b3e` pclone: implémenter le clonage récursif avec -r ainsi que les options -n et -u | ||||
| * `262048f` ufile: possibilité de classer vers plusieurs destinations | ||||
| * `8c22012` ufile: copier en local sans utiliser scp si possible | ||||
| * `dec100b` ufile: support du classement par scp | ||||
| * `c82c908` ufile: support des inclusions, d'un fichier de configuration alternatif | ||||
| * `d535df3` ufile: le code de retour de renamef peut annuler une règle | ||||
| * `0365c54` améliorer l'ergonomie de ruinst, rwoinst, toinst: pas la peine de confirmer le répertoire courant s'il est déployé sur un hôte | ||||
| * `8ce9821` fndate: améliorer l'ergonomie de l'option -@ | ||||
| * `5b0f13d` ufile: changer la sémantique de renamef | ||||
| * `fec6b2f` pu: support du scenario ou la branche de feature distante a été supprimée | ||||
| * `151433b` ufile: ajout des options --list et --edit | ||||
| * `a99f313` ufile: classement automatique de fichiers | ||||
| * `540e718` base.core: qwc supporte les classes de caractères | ||||
| * `78e0a8e` cosmetic | ||||
| * `027b416` ppath2() est plus approprié dans certaines circonstances | ||||
| * `c034115` revert 9d8b32bcd118ca9194b2d134e51a078d16b1c18d: la correction du bug était incorrecte | ||||
| * `1dbe02f` Intégration de la branche tomcat-deploy | ||||
|   * `2394edf` toinst: implémenter la sauvegarde | ||||
|   * `fc467cb` finaliser le support de .toinst.conf et traiter les options --exclude, --protect et --rsync-option | ||||
|   * `9d8b32b` parse_args: bug avec la fonction reset | ||||
|   * `9084e7e` début du support de .toinst.conf | ||||
|   * `a84775c` support des options --wamap et --protect depuis la configuration locale de déploiement | ||||
|   * `3bbabbf` deploy: support des options --of, --df, --lf | ||||
|   * `c1a536b` deploy: support des options -old pour afficher des informations supplémentaires | ||||
|   * `2daf190` quelques améliorations dont support du profil de déploiement | ||||
|   * `0b46830` implémenter toinst et rtoinst | ||||
|   * `836c933` maj doc ruinst et désactiver déploiement de clé par rwoinst | ||||
|   * `2991e63` deploy: requête récursive par défaut | ||||
|   * `52bb0d5` base.core: ajout de la fonction echo_setv2() pendant de echo_seta2() | ||||
| * `bab9c50` tailor.py: suivre un fichier est optionnel | ||||
| * `4593ad8` ajout de tailor.py: affichage d'un fichier en mettant en surbrillance certains patterns | ||||
| 
 | ||||
| ## Version 6.3.1 du 06/04/2017-22:34 | ||||
| 
 | ||||
| * `b3e6ff6` cgilsxml.py: maj doc | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| 6.3.1 | ||||
| 6.4.0 | ||||
|  | ||||
							
								
								
									
										55
									
								
								chrono.py
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								chrono.py
									
									
									
									
									
								
							| @ -273,26 +273,55 @@ def run_chronometre(timeout=None, autostart=False): | ||||
|     Application(timeout, autostart).mainloop() | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     from argparse import ArgumentParser, RawTextHelpFormatter | ||||
|     from argparse import ArgumentParser, HelpFormatter | ||||
|     if sys.argv[1:2] == ['--compat']: | ||||
|         # Avec l'argument --compat, désactiver la classe FancyHelpFormatter qui | ||||
|         # se base sur une API non documentée | ||||
|         sys.argv = sys.argv[0:1] + sys.argv[2:] | ||||
|         FancyHelpFormatter = HelpFormatter | ||||
|     else: | ||||
|         class FancyHelpFormatter(HelpFormatter): | ||||
|             """Comme HelpFormatter, mais ne touche pas aux lignes qui commencent par les | ||||
|             caractères '>>>'. Cela permet de mixer du texte formaté et du texte non | ||||
|             formaté. | ||||
|             """ | ||||
|             def _fill_text(self, text, width, indent): | ||||
|                 return ''.join([indent + line for line in text.splitlines(True)]) | ||||
|             def _split_lines(self, text, width): | ||||
|                 lines = [''] | ||||
|                 for line in text.splitlines(): | ||||
|                     if line.startswith('>>>'): | ||||
|                         lines.append(line) | ||||
|                         lines.append('') | ||||
|                     else: | ||||
|                         lines[-1] += '\n' + line | ||||
|                 lines = filter(None, lines) | ||||
|                 texts = [] | ||||
|                 for line in lines: | ||||
|                     if line.startswith('>>>'): | ||||
|                         texts.append(line[3:]) | ||||
|                     else: | ||||
|                         texts.extend(super(FancyHelpFormatter, self)._split_lines(line, width)) | ||||
|                 return texts | ||||
|     AP = ArgumentParser( | ||||
|         formatter_class=RawTextHelpFormatter, | ||||
|         usage=u"%(prog)s [options] [TIMEOUT]", | ||||
|         description=u"Afficher un chronomètre", | ||||
|         epilog=u"Si TIMEOUT est spécifié, par défaut le décompte démarre automatiquement." | ||||
|         epilog=u"Si TIMEOUT est spécifié, par défaut le décompte démarre automatiquement.", | ||||
|         formatter_class=FancyHelpFormatter, | ||||
|     ) | ||||
|     AP.set_defaults(autostart=None, timeout=None) | ||||
|     AP.add_argument('timeout', metavar='TIMEOUT', nargs='?', | ||||
|         help=u"""\ | ||||
| (valeur vide) | ||||
|     chronomètre qui démarre à 0:00 et ne s'arrête pas | ||||
| H:M:S       (heures:minutes:secondes) | ||||
| ou M:S      (minutes:secondes) | ||||
| ou M        (minutes) | ||||
|     minuteur qui démarre à H:M:S et fait un décompte jusqu'à 0:00. A la fin | ||||
|     du décompte, une sonnerie retentit. | ||||
| @H[:M[:S]] | ||||
|     minuteur qui fonctionne comme précédemment, sauf qu'on spécifie l'heure | ||||
|     d'arrivée, et que la durée est calculée automatiquement""") | ||||
| >>>    (valeur vide) | ||||
| chronomètre qui démarre à 0:00 et ne s'arrête pas | ||||
| >>>    H:M:S       (heures:minutes:secondes) | ||||
| >>> ou M:S      (minutes:secondes) | ||||
| >>> ou M        (minutes) | ||||
| minuteur qui démarre à H:M:S et fait un décompte jusqu'à 0:00. A la fin | ||||
| du décompte, une sonnerie retentit. | ||||
| >>>    @H[:M[:S]] | ||||
| minuteur qui fonctionne comme précédemment, sauf qu'on spécifie l'heure | ||||
| d'arrivée, et que la durée est calculée automatiquement""") | ||||
|     AP.add_argument('-n', '--no-autostart', dest='autostart', action='store_false', | ||||
|         help=u"Ne pas démarrer automatiquement le décompte même si TIMEOUT est spécifié.") | ||||
|     AP.add_argument('-s', '--autostart', dest='autostart', action='store_true', | ||||
|  | ||||
							
								
								
									
										57
									
								
								fndate
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								fndate
									
									
									
									
									
								
							| @ -60,9 +60,17 @@ OPTIONS | ||||
|         PLACEHOLDER vaut ~~. Si le nom spécifié ne contient pas le PLACEHOLDER, | ||||
|         il est placé au début. | ||||
|     -@, --force-date DATE | ||||
|         Dans le nom spécifié, si la date est déjà présente, forcer son | ||||
|         remplacement par la valeur spécifiée. Par défaut, le fichier n'est pas | ||||
|         modifié si la date est déjà présente. | ||||
|         Si une date du format attendu est déjà présente dans le nom du fichier, | ||||
|         forcer son remplacement par la valeur spécifiée. Par défaut, le fichier | ||||
|         n'est pas modifié si la date est déjà présente. | ||||
|         Si le premier ou le dernier argument de ce script ressemblent à une date | ||||
|         (ie. d/m[/y] ou @d[/m[/y]]) et qu'aucun fichier de ce nom n'existe dans | ||||
|         le répertoire courant, activer automatiquement cette option, sauf si | ||||
|         l'option --no-auto-force-date est spécifiée aussi. Ainsi, les commandes | ||||
|         suivantes sont équivalentes: | ||||
|             $scriptname -@ d/m/y file | ||||
|             $scriptname d/m/y file | ||||
|             $scriptname file @d/m/y | ||||
|     -F, --format FORMAT | ||||
|         Spécifier le format de la date à insérer dans le nom du fichier. Par | ||||
|         défaut, FORMAT vaut 'YYMMDD-' | ||||
| @ -227,6 +235,7 @@ dmove) action=move;; | ||||
| dcmd) action=cmd;; | ||||
| esac | ||||
| placeholder= | ||||
| auto_force_date=1 | ||||
| force_date= | ||||
| format= | ||||
| autof= | ||||
| @ -240,6 +249,7 @@ parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     -c,--cmd action=cmd \ | ||||
|     --string action=string \ | ||||
|     -P:,--placeholder: placeholder= \ | ||||
|     --no-auto-force-date auto_force_date= \ | ||||
|     -@:,--force-date: force_date= \ | ||||
|     -F:,--format: format= \ | ||||
|     -s,--short '$format=YYMMDD; autof=1' \ | ||||
| @ -247,6 +257,27 @@ parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --autof autof=1 \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| if [ -z "$force_date" -a -n "$auto_force_date" ]; then | ||||
|     # si le premier ou le dernier argument ressemblent à une date | ||||
|     f="$1"; f2="${f#@}" | ||||
|     if [[ "$f" == */* ]] && [ -z "${f//[0-9\/]}" -a ! -e "$f" ]; then | ||||
|         force_date="$f" | ||||
|         shift | ||||
|     elif [[ "$f" == @* ]] && [ -z "${f2//[0-9\/]}" -a ! -e "$f2" ]; then | ||||
|         force_date="$f2" | ||||
|         shift | ||||
|     elif [ $# -gt 1 ]; then | ||||
|         l="${@:$#}"; l2="${l#@}" | ||||
|         if [[ "$l" == */* ]] && [ -z "${l//[0-9\/]}" -a ! -e "$l" ]; then | ||||
|             force_date="$l" | ||||
|             set -- "${@:1:$(($# - 1))}" | ||||
|         elif [[ "$l" == @* ]] && [ -z "${l2//[0-9\/]}" -a ! -e "$l2" ]; then | ||||
|             force_date="$l2" | ||||
|             set -- "${@:1:$(($# - 1))}" | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| [ -n "$create" ] || create=file | ||||
| [ -n "$placeholder" ] || placeholder="~~" | ||||
| [ -n "$force_date" ] && setx force_date=parse_date "$force_date" | ||||
| @ -329,14 +360,24 @@ elif [ "$action" == create ]; then | ||||
|             setx dir=dirname -- "$src" | ||||
|             setx srcname=basename -- "$src" | ||||
|             if [ -e "$src" ]; then | ||||
|                 estep "Renommage de $(ppath "$src")" | ||||
|                 setx destname=replace_ph "$srcname" "$force_date" | ||||
|                 setx dest=abspath "$dir/$destname" | ||||
|                 [ "$src" != "$dest" ] || ewarn "La source et la destination sont identiques" | ||||
|                 read_value "Veuillez confirmer le nom" destname "$destname" | ||||
|                 confirm_do=1 | ||||
|                 if [ "$src" == "$dest" ]; then | ||||
|                     if [ -n "$force_date" ]; then | ||||
|                         ewarn "La source et la destination sont identiques" | ||||
|                     else | ||||
|                         estepi "$(ppath "$src"): aucun renommage nécessaire" | ||||
|                         confirm_do= | ||||
|                     fi | ||||
|                 fi | ||||
|                 if [ -n "$confirm_do" ]; then | ||||
|                     estep "Renommage de $(ppath "$src")" | ||||
|                     read_value "Veuillez confirmer le nom" destname "$destname" | ||||
| 
 | ||||
|                 setx dest=abspath "$dir/$destname" | ||||
|                 [ "$src" != "$dest" ] && mv -i "$src" "$dir/$destname" | ||||
|                     setx dest=abspath "$dir/$destname" | ||||
|                     [ "$src" != "$dest" ] && mv -i "$src" "$dir/$destname" | ||||
|                 fi | ||||
|             else | ||||
|                 setx destname=replace_ph "$srcname" "$force_date" | ||||
|                 setx dest=abspath "$dir/$destname" | ||||
|  | ||||
| @ -1,13 +1,21 @@ | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| 
 | ||||
| function __nutools_host_completion() { | ||||
|     local cur prev | ||||
|     _get_comp_words_by_ref cur prev | ||||
|     if [ "$prev" == "-h" -o "$prev" == "-H" ]; then | ||||
|     local cur prev; _get_comp_words_by_ref cur prev | ||||
|     [ "$prev" == "-h" -o "$prev" == "-H" -o "$prev" == "--host" ] && _known_hosts_real "$cur" | ||||
|     return 0 | ||||
| } | ||||
| function __nutools_whost_completion() { | ||||
|     local cur prev; _get_comp_words_by_ref cur prev | ||||
|     if [ "$prev" == "-h" -o "$prev" == "-H" -o "$prev" == "--host" ]; then | ||||
|         _known_hosts_real "$cur" | ||||
|     elif [ "$prev" == "-w" -o "$prev" == "--whost" ]; then | ||||
|         _known_hosts_real "$cur" | ||||
|     fi | ||||
|     return 0 | ||||
| } | ||||
| complete -F __nutools_host_completion -o default uinst ruinst runs rruns | ||||
| complete -F __nutools_host_completion -o default uinst ruinst runs rruns rwoinst rtoinst | ||||
| complete -F __nutools_whost_completion -o default rwoinst | ||||
| 
 | ||||
| if __bash_completion_module_enabled ssh; then | ||||
|     shopt -u hostcomplete | ||||
|  | ||||
							
								
								
									
										9
									
								
								lib/default/ufile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lib/default/ufile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| 
 | ||||
| # Fichiers externes à inclure. Chacun de ces fichiers peut contenir des | ||||
| # définitions de fonctions et de la variables RULES | ||||
| INCLUDES=() | ||||
| 
 | ||||
| # Règles pour le classement des fichiers. Chaque règle est de la forme | ||||
| # pattern:destdir[:renamef] | ||||
| RULES=() | ||||
| @ -412,7 +412,7 @@ if test "\$keep" = n; then | ||||
| fi | ||||
| eval \$finish; | ||||
| if test x"\$tmp_archive" = xy; then | ||||
|     exec /bin/rm -f "\$thisarch" | ||||
|     /bin/rm -f "\$thisarch"; exit \$res | ||||
| else | ||||
|     exit \$res | ||||
| fi | ||||
|  | ||||
| @ -548,6 +548,19 @@ function ppath() { | ||||
| 
 | ||||
|     recho "$path" | ||||
| } | ||||
| function ppath2() { | ||||
| # Comme ppath() mais afficher '.' comme '../$dirname' | ||||
|     local path="$1" cwd="$2" | ||||
| 
 | ||||
|     path="$(abspath "$path")" # essayer de normaliser le chemin | ||||
|     [ -n "$cwd" ] || cwd="$(pwd)" | ||||
| 
 | ||||
|     [ "$path" = "$cwd" ] && path="../$(basename -- "$path")" | ||||
|     [ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path#$cwd/}" | ||||
|     [ "${path#$HOME/}" != "$path" ] && path="~${path#$HOME}" | ||||
| 
 | ||||
|     recho "$path" | ||||
| } | ||||
| function relpath() { | ||||
| # Afficher le chemin relatif de $1 par rapport à $2. Si $2 n'est pas spécifié, | ||||
| # on prend le répertoire courant. Si $1 ou $2 ne sont pas des chemins absolus, | ||||
|  | ||||
| @ -86,9 +86,10 @@ function __po_parse_optdescs() { | ||||
|                 elif [[ "$optdesc_" == *:: ]]; then | ||||
|                     option_="${optdesc_%::}" | ||||
|                     if [[ "$2" == *=* ]]; then | ||||
|                         # la valeur mentionnée est toujours ignorée | ||||
|                         # la valeur mentionnée est toujours ignorée. le '=' à la | ||||
|                         # fin est utilisé par __po_process_options() ci-dessous. | ||||
|                         name_="${2%%=*}=" | ||||
|                         [ -n "$reset_" ] && eval "$name_=" | ||||
|                         [ -n "$reset_" ] && eval "$name_" | ||||
|                     else | ||||
|                         name_="$2" | ||||
|                         [ -n "$reset_" ] && eval "$name_=()" | ||||
| @ -97,9 +98,10 @@ function __po_parse_optdescs() { | ||||
|                 elif [[ "$optdesc_" == *: ]]; then | ||||
|                     option_="${optdesc_%:}" | ||||
|                     if [[ "$2" == *=* ]]; then | ||||
|                         # la valeur mentionnée est toujours ignorée | ||||
|                         # la valeur mentionnée est toujours ignorée. le '=' à la | ||||
|                         # fin est utilisé par __po_process_options() ci-dessous. | ||||
|                         name_="${2%%=*}=" | ||||
|                         [ -n "$reset_" ] && eval "$name_=" | ||||
|                         [ -n "$reset_" ] && eval "$name_" | ||||
|                     else | ||||
|                         name_="$2" | ||||
|                         [ -n "$reset_" ] && eval "$name_=()" | ||||
| @ -108,7 +110,7 @@ function __po_parse_optdescs() { | ||||
|                 else | ||||
|                     option_="$optdesc_" | ||||
|                     name_="$2" | ||||
|                     [ -n "$reset_" ] && eval "$name_=" | ||||
|                     [ -n "$reset_" ] && eval "${2%%=*}=" | ||||
|                     flag_= | ||||
|                 fi | ||||
| 
 | ||||
|  | ||||
| @ -107,7 +107,7 @@ function qvals() { | ||||
| } | ||||
| function qwc() { | ||||
| # Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \`, puis | ||||
| # quoter la chaine avec ", sauf les wildcards * et ? | ||||
| # 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 | ||||
| @ -119,44 +119,45 @@ function qwc() { | ||||
|     s="${s//\"/\\\"}" | ||||
|     s="${s//\$/\\\$}" | ||||
|     s="${s//\`/\\\`}" | ||||
|     local r a b | ||||
|     local r a b c | ||||
|     while [ -n "$s" ]; do | ||||
|         if [[ "$s" == *\** ]]; then | ||||
|             if [[ "$s" == *\?* ]]; then | ||||
|                 a="${s%%\**}" | ||||
|                 b="${s%%\?*}" | ||||
|                 if [ ${#a} -lt ${#b} ]; then | ||||
|                     s="${s#*\*}" | ||||
|                     r="$r\"$a\"*" | ||||
|                 else | ||||
|                     s="${s#*\?}" | ||||
|                     r="$r\"$b\"?" | ||||
|                 fi | ||||
|             else | ||||
|                 a="${s%%\**}" | ||||
|                 s="${s#*\*}" | ||||
|                 r="$r\"$a\"*" | ||||
|             fi | ||||
|         elif [[ "$s" == *\?* ]]; then | ||||
|             if [[ "$s" == *\** ]]; then | ||||
|                 a="${s%%\**}" | ||||
|                 b="${s%%\?*}" | ||||
|                 if [ ${#a} -lt ${#b} ]; then | ||||
|                     s="${s#*\*}" | ||||
|                     r="$r\"$a\"*" | ||||
|                 else | ||||
|                     s="${s#*\?}" | ||||
|                     r="$r\"$b\"?" | ||||
|                 fi | ||||
|             else | ||||
|                 a="${s%%\?*}" | ||||
|                 s="${s#*\?}" | ||||
|                 r="$r\"$a\"?" | ||||
|             fi | ||||
|         else | ||||
|         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" | ||||
| } | ||||
| @ -191,6 +192,22 @@ function echo_setv() { | ||||
|     fi | ||||
|     echo "$__s_var=$(qvalr "$*")" | ||||
| } | ||||
| function echo_setv2() { | ||||
| # Afficher la commande qui recrée la variable $1 | ||||
| # Cette fonction est équivalente à  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() | ||||
|     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 | ||||
| @ -219,8 +236,8 @@ function echo_seta() { | ||||
| } | ||||
| function echo_seta2() { | ||||
| # Afficher la commande qui recrée le tableau $1 | ||||
| # Si des arguments sont spécifiés, cette fonction se comporte comme | ||||
| # echo_seta() | ||||
| # Si d'autres arguments que le nom de tableau sont spécifiés, cette fonction se | ||||
| # comporte comme echo_seta() | ||||
|     local __s_var="$1"; shift | ||||
|     if [[ "$__s_var" == *=* ]]; then | ||||
|         set -- "${__s_var#*=}" "$@" | ||||
|  | ||||
| @ -6,15 +6,44 @@ | ||||
| # API publique | ||||
| 
 | ||||
| function deploy_query() { | ||||
|     deploy_query_once "$@" && return 0 | ||||
|     if [ -n "$QUERYVARS" ]; then | ||||
|         deploy_query_recursive "$@" && return 0 | ||||
|     fi | ||||
|     return 1 | ||||
| } | ||||
| 
 | ||||
| function deploy_query_recursive() { | ||||
|     local DFILE | ||||
|     for DFILE in "${QUERYVARS[@]}"; do | ||||
|         ( | ||||
|             deploy_loadconf --no-auto-update | ||||
|             deploy_query_once "$@" && exit 0 | ||||
|             if [ -n "$QUERYVARS" ]; then | ||||
|                 deploy_query_recursive "$@" && exit 0 | ||||
|             fi | ||||
|             exit 1 | ||||
|         ) && return 0 | ||||
|     done | ||||
|     return 1 | ||||
| } | ||||
| 
 | ||||
| function deploy_query_once() { | ||||
|     # Afficher le résultat d'une requête | ||||
|     local alv | ||||
|     eval "set -- $(getopt -ov: -lallow-vars: -- "$@")" | ||||
|     local alv sov sdv slv sof sdf slf | ||||
|     eval "set -- $(getopt -ov:odl -lallow-vars:,object-vars,dest-vars,link-vars,of:,object-func:,df:,dest-func:,lf:,link-func: -- "$@")" | ||||
|     while [ -n "$1" ]; do | ||||
|         case "$1" in | ||||
|         -v|--allow-vars) | ||||
|             array_split alv "$2" , | ||||
|             shift; shift | ||||
|             ;; | ||||
|         -o|--object-vars) sov=1; shift;; | ||||
|         -d|--dest-vars) sdv=1; shift;; | ||||
|         -l|--link-vars) slv=1; shift;; | ||||
|         --of|--object-func) sof="$2"; shift; shift;; | ||||
|         --df|--dest-func) sdf="$2"; shift; shift;; | ||||
|         --lf|--link-func) slf="$2"; shift; shift;; | ||||
|         --) shift; break;; | ||||
|         *) break;; | ||||
|         esac | ||||
| @ -27,7 +56,7 @@ function deploy_query() { | ||||
|     DEST|SOURCE) | ||||
|         if [ -n "$otype" ]; then | ||||
|             deploy_is_type "$otype" || { | ||||
|                 qvals false "$otype: invalid type" | ||||
|                 [ "$format" == shell ] && qvals false "$otype: invalid type" | ||||
|                 return 2 | ||||
|             } | ||||
|         fi | ||||
| @ -35,7 +64,7 @@ function deploy_query() { | ||||
|     *) | ||||
|         if [ -n "$qtype" ]; then | ||||
|             deploy_is_type "$qtype" || { | ||||
|                 qvals false "$qtype: invalid type" | ||||
|                 [ "$format" == shell ] && qvals false "$qtype: invalid type" | ||||
|                 return 3 | ||||
|             } | ||||
|         fi | ||||
| @ -43,12 +72,12 @@ function deploy_query() { | ||||
|     esac | ||||
|     if [ -n "$ltype" ]; then | ||||
|         deploy_is_link "$ltype" || { | ||||
|             qvals false "$ltype: invalid link type" | ||||
|             [ "$format" == shell ] && qvals false "$ltype: invalid link type" | ||||
|             return 4 | ||||
|         } | ||||
|     fi | ||||
|     [ -n "$term" ] || { | ||||
|         qvals false "search term required" | ||||
|         [ "$format" == shell ] && qvals false "search term required" | ||||
|         return 5 | ||||
|     } | ||||
| 
 | ||||
| @ -57,23 +86,40 @@ function deploy_query() { | ||||
|         edebug "=== search type DEST" | ||||
|         edebug "term=$term, otype=$otype" | ||||
|         deploy_search_artifact object type "$term" "$otype" host || { | ||||
|             qvals false "artifact not found" | ||||
|             [ "$format" == shell ] && qvals false "artifact not found" | ||||
|             return 1 | ||||
|         } | ||||
|         edebug "object=$object, type=$type" | ||||
|         deploy_search_link link "$type" "$ltype" || { | ||||
|             qvals false "link not found" | ||||
|             [ "$format" == shell ] && qvals false "link not found" | ||||
|             return 1 | ||||
|         } | ||||
|          | ||||
|         deploy_show_values object object "$format" shell alv | ||||
|         deploy_show_values type otype "$format" shell alv | ||||
|         deploy_show_values link ltype "$format" shell alv | ||||
|         deploy_show_links "$object" "$link" "$profile" "$format" "" alv | ||||
|         if [ -n "$sov" ]; then | ||||
|             deploy_copy_object_values vs "$object" "$type" | ||||
|             deploy_show_values vs "$type" "$format" shell alv | ||||
|             deploy_show_attrs "$object" "$type" "$format" alv vars "$sof" | ||||
|         fi | ||||
|         if [ -n "$sdv" ]; then | ||||
|             local -a pons pgns ons gns ans ovs os; local an av o | ||||
|             deploy_prepare_copy_link_attrs pons pgns ons gns "$object" "$link" "$profile" | ||||
|             deploy_copy_link_attr_values hvs host "$object" "$link" "$profile" pons pgns ons gns | ||||
|             for hv in "${hvs[@]}"; do | ||||
|                 deploy_copy_object_values hs "$hv" host | ||||
|                 deploy_show_values hs host "$format" shell alv | ||||
|                 deploy_show_attrs "$hn" host "$format" alv vars "$sdf" | ||||
|             done | ||||
|         fi | ||||
|         deploy_show_links "$object" "$link" "$profile" "$format" "" alv vars "$slf" | ||||
|         [ "$format" == shell ] && echo true | ||||
|         return 0 | ||||
|         ;; | ||||
|     SOURCE) | ||||
|         # XXX implémenter | ||||
|         [ "$format" == shell ] && echo true | ||||
|         return 0 | ||||
|         ;; | ||||
|     *) | ||||
| @ -83,9 +129,10 @@ function deploy_query() { | ||||
|             deploy_show_values type otype "$format" shell alv | ||||
|             deploy_show_values vs "$type" "$format" ""  alv | ||||
|             deploy_show_attrs "$object" "$type" "$format" alv | ||||
|             [ "$format" == shell ] && echo true | ||||
|             return 0 | ||||
|         fi | ||||
|         qvals false "artifact not found" | ||||
|         [ "$format" == shell ] && qvals false "artifact not found" | ||||
|         return 1 | ||||
|         ;; | ||||
|     esac | ||||
| @ -224,10 +271,7 @@ function deploy_show_values() { | ||||
|     [ -n "$ff" -a "$f" != "$ff" ] && return | ||||
| 
 | ||||
|     case "$f" in | ||||
|     shell) | ||||
|         [ -n "$5" ] && echo "$t=()" | ||||
|         deploy_dump_values "$t" vs | ||||
|         ;; | ||||
|     shell) deploy_dump_values "$t" vs;; | ||||
|     line) array_to_lines vs;; | ||||
|     *) array_join vs "$f";; | ||||
|     esac | ||||
| @ -244,16 +288,17 @@ function deploy_show_attrs() { | ||||
|     local -a ons gns ans vs; local an | ||||
|     deploy_prepare_copy_attrs ons gns "$o" "$t" | ||||
|     deploy_copy_attr_names ans "$o" "$t" ons gns | ||||
|     [ -n "$5" ] && echo_seta "${t}_vars" "${ans[@]}" | ||||
|     for an in "${ans[@]}"; do | ||||
|         if [ -n "$4" ]; then | ||||
|             if ! array_isempty "$4"; then | ||||
|                 array_contains alv "$an" || continue | ||||
|             fi | ||||
|             [ "$f" == shell ] && echo "$an=()" | ||||
|         fi | ||||
|         deploy_copy_attr_values vs "$an" "$o" "$t" ons | ||||
|         deploy_dump_values "$an" vs | ||||
|     done | ||||
|     [ -n "$6" ] && echo "$6" | ||||
| } | ||||
| 
 | ||||
| function deploy_show_links() { | ||||
| @ -272,6 +317,7 @@ function deploy_show_links() { | ||||
| 
 | ||||
|         deploy_prepare_copy_link_attrs pons pgns ons gns "$o" "$l" "$p" | ||||
|         deploy_copy_link_attr_names ans "$o" "$l" "$p" pons pgns ons gns | ||||
|         [ -n "$7" -a "$f" == shell ] && echo_seta "${l}_vars" "${ans[@]}" | ||||
|         for an in "${ans[@]}"; do | ||||
|             deploy_copy_link_attr_values avs "$an" "$o" "$l" "$p" pons pgns ons gns | ||||
|             if [ "$an" == host ]; then | ||||
| @ -287,6 +333,7 @@ function deploy_show_links() { | ||||
|                 deploy_show_values avs "$an" "$f" shell alv | ||||
|             fi | ||||
|         done | ||||
|         [ -n "$8" -a "$f" == shell ] && echo "$8" | ||||
|     done | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										57
									
								
								lib/ulib/vcs
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								lib/ulib/vcs
									
									
									
									
									
								
							| @ -456,11 +456,64 @@ function git_update() { | ||||
|         return $? | ||||
|     fi | ||||
| 
 | ||||
|     local orig_branch restore_branch remote rbranch pbranch | ||||
|     local -a branches | ||||
|     local branch orig_branch restore_branch remote rbranch pbranch | ||||
|     local -a branches prbranches crbranches dbranches | ||||
| 
 | ||||
|     array_from_lines prbranches "$(git_list_rbranches)" | ||||
|     git fetch -p "$@" || return | ||||
|     array_from_lines 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 ! array_contains crbranches "$branch"; then | ||||
|             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 | ||||
|                     array_del dbranches "$branch" | ||||
|                 fi | ||||
|             fi | ||||
|         done | ||||
|     fi | ||||
|     if [ ${#dbranches[*]} -gt 0 ]; then | ||||
|         array_from_lines branches "$(git_list_branches)" | ||||
|         branch="$(git_get_branch)" | ||||
|         if 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" ] && array_contains branches develop && ! array_contains dbranches develop; then | ||||
|                 swto=develop | ||||
|             fi | ||||
|             if [ -z "$swto" ] && array_contains branches master && ! 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")" | ||||
|  | ||||
							
								
								
									
										131
									
								
								lib/ulib/woinst
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								lib/ulib/woinst
									
									
									
									
									
								
							| @ -410,27 +410,52 @@ OPTIONS | ||||
|     PREFIX=value | ||||
|         Spécifier une valeur pour un préfixe, plutôt que de laisser uprefix | ||||
|         l'autodétecter. Utiliser uprefix -l pour une liste de préfixes valides. | ||||
|     -b  Redémarrer les instances en mode bounce. | ||||
|         Par défaut, les instances sont arrêtées avant le déploiement, et | ||||
|         redémarrées après | ||||
|     -W  Ne déployer que les resources web. Implique -n | ||||
|     -n  Ne pas tagger les bundles déployés avec un numéro de version. Par | ||||
|         défaut, l'utilisateur est invité à compléter des informations telles | ||||
|         que n° de version et date de release si ces informations ne sont pas | ||||
|     --prefix | ||||
|         Corriger les chemins des variables qui commencent par des préfixes | ||||
|         valides (c'est la valeur par défaut). Utiliser 'uprefix -l' pour avoir | ||||
|         une liste de préfixes valides | ||||
|     --no-prefix | ||||
|         Ne jamais corriger un chemin. | ||||
|     -W, --webres | ||||
|         Ne déployer que les resources web. Implique -n | ||||
|     -n, --no-tag | ||||
|         Ne pas tagger les bundles déployés avec un numéro de version. En temps | ||||
|         normal, l'utilisateur est invité à compléter des informations telles que | ||||
|         n° de version et date de release si ces informations ne sont pas | ||||
|         disponible. | ||||
|     -x CMD | ||||
|     -d, --active-dbconfig DBCONFIG | ||||
|         Spécifier le profil de connexion à utiliser par défaut pour tous les | ||||
|         eomodels du bundle. S'il faut un profil différent en fonction de l'eomodel, utiliser l'option -m | ||||
|     -m, --active-dbconfig-map EOMODEL:DBCONFIG | ||||
|         Spécifier un mapping entre un nom d'eomodel et le profil de connexion à | ||||
|         utiliser. Pour les eomodels qui ne sont pas spécifiés, la valeur par | ||||
|         défaut est utilisée si elle existe. Il est possible de spécifier | ||||
|         plusieurs mappings en les séparant par des virgules. | ||||
|     --stop-start | ||||
|         Redémarrer les instances de la manière classique: les instances sont | ||||
|         arrêtées avant le déploiement, et redémarrées après. C'est la valeur par | ||||
|         défaut. | ||||
|     -b, --bounce | ||||
|         Redémarrer les instances en mode bounce. | ||||
|     -x, --exec CMD | ||||
|         Exécuter la commande CMD après avoir effectué le déploiement" | ||||
|     } | ||||
| 
 | ||||
|     local bounce webinst notag scripts istmpdir tmpdir | ||||
|     scripts=() | ||||
|     local istmpdir tmpdir autoprefix=1 bounce webinst notag default_dbconfig | ||||
|     local -a dbconfigs scripts | ||||
|     parse_opts "${PRETTYOPTS[@]}" \ | ||||
|         --help '$exit_with __woinst_display_help' \ | ||||
|         -b,--bounce bounce=1 \ | ||||
|         -W,--webres webinst=1 \ | ||||
|         -n,--notag notag=1 \ | ||||
|         -x:,--exec: scripts \ | ||||
|         --is-tmpdir '$istmpdir=1; tmpdir=.' \ | ||||
|         --prefix autoprefix=1 \ | ||||
|         --no-prefix autoprefix= \ | ||||
|         -W,--webres webinst=1 \ | ||||
|         --tag notag= \ | ||||
|         -n,--no-tag notag=1 \ | ||||
|         -d:,--active-dbconfig: default_dbconfig= \ | ||||
|         -m:,--active-dbconfig-map: dbconfigs \ | ||||
|         --stop-start bounce= \ | ||||
|         -b,--bounce bounce=1 \ | ||||
|         -x:,--exec: scripts \ | ||||
|         @ args -- "$@" && | ||||
|     set -- "${args[@]}" || { | ||||
|         eerror "$args" | ||||
| @ -457,7 +482,8 @@ OPTIONS | ||||
|     for src in "${@:-.}"; do | ||||
|         if [[ "$src" == *=* ]]; then | ||||
|             splitvar "$src" name value | ||||
|             array_add variables "$name" | ||||
|             array_addu variables "$name" | ||||
|             [ -n "$autoprefix" ] && value="$(expand_prefix "$value")" | ||||
|             _setv "$name" "$value" | ||||
|         else | ||||
|             src="$(abspath "$src")" | ||||
| @ -469,6 +495,19 @@ OPTIONS | ||||
|                 copied=1 | ||||
|             fi | ||||
|             if [ -d "$src" ]; then | ||||
|                 setx name=basename -- "$src" | ||||
|                 case "$src" in | ||||
|                 *.woa|*.framework) ;; | ||||
|                 *) # support projet maven | ||||
|                     if [ ! -f "$src/pom.xml" ]; then | ||||
|                         : # non, pas un projet maven | ||||
|                     elif [ -d "$src/target/$name.woa" ]; then | ||||
|                         src="$src/target/$name.woa" | ||||
|                     elif [ -d "$src/target/$name.framework" ]; then | ||||
|                         src="$src/target/$name.framework" | ||||
|                     fi | ||||
|                     ;; | ||||
|                 esac | ||||
|                 if endswith "$src" .framework; then | ||||
|                     is_wofwkdir "$src" || { | ||||
|                         eerror "Framework invalide: $(ppath "$src")" | ||||
| @ -504,6 +543,68 @@ OPTIONS | ||||
|     done | ||||
|     eend | ||||
| 
 | ||||
|     # Corriger les eomodelds | ||||
|     array_fix_paths dbconfigs , | ||||
|     if [ -n "$default_dbconfig" -o ${#dbconfigs[*]} -gt 0 ]; then | ||||
|         etitle "Configuration des eomodels" | ||||
|         local -a eonames eomodels tmpeomodels | ||||
|         local eom dbc eoname eomodel dbconfig found | ||||
| 
 | ||||
|         estep "Calcul de la liste des eomodels" | ||||
|         if [ ${#dbconfigs[*]} -eq 0 ]; then | ||||
|             for src in "${frameworks[@]}"; do | ||||
|                 array_from_lines tmpeomodels "$(find "$src" -type d -name "*.eomodeld")" | ||||
|                 for eom in "${tmpeomodels[@]}"; do | ||||
|                     array_addu eonames "$(basename -- "$eom")" | ||||
|                 done | ||||
|             done | ||||
|             for src in "${applications[@]}"; do | ||||
|                 array_from_lines tmpeomodels "$(find "$src" -type d -name "*.eomodeld")" | ||||
|                 for eom in "${tmpeomodels[@]}"; do | ||||
|                     array_addu eonames "$(basename -- "$eom")" | ||||
|                 done | ||||
|             done | ||||
|         else | ||||
|             for dbc in "${dbconfigs[@]}"; do | ||||
|                 splitpair "$dbc" eom dbc | ||||
|                 [ "${eom%.eomodeld}" != "$eom" ] || eom="$eom.eomodeld" | ||||
|                 array_addu eonames "$(basename -- "$eom")" | ||||
|             done | ||||
|         fi | ||||
|         for eom in "${eonames[@]}"; do | ||||
|             for src in "${frameworks[@]}"; do | ||||
|                 array_from_lines tmpeomodels "$(find "$src" -type d -name "$eom")" | ||||
|                 array_extendu eomodels tmpeomodels | ||||
|             done | ||||
|             for src in "${applications[@]}"; do | ||||
|                 array_from_lines tmpeomodels "$(find "$src" -type d -name "$eom")" | ||||
|                 array_extendu eomodels tmpeomodels | ||||
|             done | ||||
|         done | ||||
| 
 | ||||
|         for eomodel in "${eomodels[@]}"; do | ||||
|             setx eoname=basename -- "$eomodel" | ||||
|             if [ ! -f "$eomodel/index.eomodeld" ]; then | ||||
|                 ewarn "$eomodel: eomode invalide" | ||||
|                 continue | ||||
|             fi | ||||
|             found= | ||||
|             for dbc in "${dbconfigs[@]}"; do | ||||
|                 splitpair "$dbc" eom dbconfig | ||||
|                 [ "${eom%.eomodeld}" != "$eom" ] || eom="$eom.eomodeld" | ||||
|                 if [ "$(basename -- "$eom")" == "$eoname" ]; then | ||||
|                     found="$dbconfig" | ||||
|                     break | ||||
|                 fi | ||||
|             done | ||||
|             [ -z "$found" -a -n "$default_dbconfig" ] && found="$default_dbconfig" | ||||
|             if [ -n "$found" ]; then | ||||
|                 estep "$eomodel [$found]" | ||||
|                 sed -i "/^ *activeDatabaseConfigName *=/s/=.*;/=\"$found\";/" "$eomodel/index.eomodeld" | ||||
|             fi | ||||
|         done | ||||
|     fi | ||||
| 
 | ||||
|     # Tagger les bundles | ||||
|     if [ -z "$webinst" -a -z "$notag" ]; then | ||||
|         etitle "Tagger les bundles" | ||||
|  | ||||
							
								
								
									
										267
									
								
								rtoinst
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										267
									
								
								rtoinst
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,267 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS pyulib/pyulib | ||||
| 
 | ||||
| function display_help() { | ||||
|     uecho "$scriptname: Déploiement distant avec toinst | ||||
| 
 | ||||
| USAGE | ||||
|     $scriptname [-h host] [-T tmproot] <archive|dir> [-- options de toinst] | ||||
| 
 | ||||
| note: à cause d'une limitation de makeself, les options de toinst ne devraient | ||||
| pas contenir d'espaces ni de caractères spéciaux. L'échappement de ces | ||||
| caractères n'est pas garanti. | ||||
| 
 | ||||
| OPTIONS | ||||
|     -T, --tmproot TMPROOT | ||||
|         Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple | ||||
|         /var/tmp. Cette option est utile pour les vservers, qui ont par défaut | ||||
|         un /tmp minuscule de 16 Mo. | ||||
|     -S, --ssh SSH | ||||
|         Spécifier le programme à utiliser pour la connection par ssh. | ||||
|     -h, --host hosts | ||||
|     -h, --host @hostsfile | ||||
|         Spécifier un ou plusieurs hôtes sur lequels faire le déploiement. Pour | ||||
|         spécifier plusieurs hôtes, il est possible d'utiliser plusieurs fois | ||||
|         l'option -h, ou spécifier en une seule fois plusieurs hôtes en les | ||||
|         séparant par un espace ou le caractère ':', e.g. 'host1 host2' ou | ||||
|         'host1:host2'. Si la spécification contient les caractères { et }, | ||||
|         l'expansion est effectuée, e.g | ||||
|             -h 'root@{host1,host2}.univ.run' | ||||
|         Par défaut, la connexion sur l'hôte distant se fait avec l'utilisateur | ||||
|         root. Il est possible de spécifier un autre utilisateur avec la syntaxe | ||||
|         user@host, e.g -h user@host | ||||
|         La forme @hostsfile permet de lire la liste des hôtes depuis le fichier | ||||
|         hostsfile, à raison d'un hôte par ligne. | ||||
|     --deploy | ||||
|     --no-deploy | ||||
|         Autoriser (respectivement interdire) l'utilisation de la configuration | ||||
|         locale de déploiement pour identifier la destination si aucun hôte n'est | ||||
|         spécifié. | ||||
|         Par défaut, si aucun hôte n'est spécifié, la configuration locale de | ||||
|         déploiement est interrogée pour avoir cette information. | ||||
|     -c, --deploy-config CONFNAME | ||||
|         Spécifier le nom de la configuration à utiliser pour l'interrogation de | ||||
|         la configuration locale de déploiement. Par défaut, utiliser le nom | ||||
|         'rtoinst' | ||||
|     -p, --deploy-profile PROFILE | ||||
|         Spécifier le profil à utiliser pour l'interrogation de la configuration | ||||
|         locale de déploiement. Par défaut, aucun profil n'est sélectionné." | ||||
| } | ||||
| 
 | ||||
| __PARSED_HOSTS=() | ||||
| __PARSED_FILES=() | ||||
| function parse_hostsfile() { | ||||
|     # Lire chacun des fichiers $* et initialiser __PARSED_HOSTS avec la liste | ||||
|     # des hôtes mentionnés dans les fichiers. | ||||
|     local inputfile basedir inputs input | ||||
|     for inputfile in "$@"; do | ||||
|         inputfile="$(abspath "$inputfile")" | ||||
|         array_contains __PARSED_FILES "$inputfile" && { | ||||
|             ewarn "$(ppath "$inputfile"): inclusion récursive" | ||||
|             continue | ||||
|         } | ||||
|         array_add __PARSED_FILES "$inputfile" | ||||
|         basedir="$(dirname "$inputfile")" | ||||
| 
 | ||||
|         array_from_lines inputs "$(<"$inputfile" filter_conf)" || { | ||||
|             ewarn "$inputfile: fichier ingnoré" | ||||
|             continue | ||||
|         } | ||||
|         for input in "${inputs[@]}"; do | ||||
|             if [ "${input#@}" != "$input" ]; then | ||||
|                 # fichier inclus | ||||
|                 parse_hostsfile "$(abspath "${input#@}" "$basedir")" | ||||
|             else | ||||
|                 array_addu __PARSED_HOSTS "$input" | ||||
|             fi | ||||
|         done | ||||
|     done | ||||
| } | ||||
| function __expand_braces() { | ||||
|     if [[ "$1" == *{* ]] && [[ "$1" == *}* ]]; then | ||||
|         eval "echo $1" | ||||
|     else | ||||
|         echo "$1" | ||||
|     fi | ||||
| } | ||||
| function __dot_is_localhost() { [ "$1" == "." ] && echo "localhost" || echo "$1"; } | ||||
| function fix_hosts() { | ||||
|     # Si hosts contient des éléments multiple, comme a:b, séparer ces | ||||
|     # éléments. i.e (a b:c) --> (a b c) | ||||
|     # Supporter la syntaxe @hostsfile qui permet de charger la liste des hôtes | ||||
|     # depuis un fichier. | ||||
|     # Remplacer aussi les '.' par 'localhost' | ||||
|     array_map hosts __expand_braces | ||||
|     array_fix_paths hosts ":" | ||||
|     array_fix_paths hosts " " | ||||
| 
 | ||||
|     local -a _hosts _tmphosts host | ||||
|     for host in "${hosts[@]}"; do | ||||
|         host="${host%/}" | ||||
|         if [ "${host#@}" != "$host" ]; then | ||||
|             __PARSED_HOSTS=() | ||||
|             parse_hostsfile "${host#@}" | ||||
|             array_fix_paths __PARSED_HOSTS | ||||
|             array_extendu _hosts __PARSED_HOSTS | ||||
|         else | ||||
|             array_addu _hosts "$host" | ||||
|         fi | ||||
|     done | ||||
|     array_copy hosts _hosts | ||||
|     array_map hosts __dot_is_localhost | ||||
| } | ||||
| 
 | ||||
| action=deploy | ||||
| tmproot= | ||||
| SSH= | ||||
| hosts=() | ||||
| deploy_enable=1 | ||||
| deploy_confname=rtoinst | ||||
| deploy_profile= | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -T:,--tmproot: tmproot= \ | ||||
|     -S:,--ssh: SSH= \ | ||||
|     -h:,-H:,--host: hosts \ | ||||
|     --deploy deploy_enable=1 \ | ||||
|     --no-deploy deploy_enable= \ | ||||
|     -c:,--deploy-config: deploy_confname= \ | ||||
|     -p:,--deploy-profile: deploy_profile= \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| : "${SSH:=ssh}" | ||||
| 
 | ||||
| ## webapp à déployer et hôtes sur lesquels faire le déploiement | ||||
| confirm_webapp= | ||||
| if [ $# -eq 0 ] || [[ "$1" == -* ]]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de toinst) | ||||
|     [ -d WEB-INF ] && webapp=. || webapp= | ||||
|     confirm_webapp=1 | ||||
| else | ||||
|     webapp="$1" | ||||
| fi | ||||
| 
 | ||||
| toinst_options=() | ||||
| if array_isempty hosts && [ -n "$deploy_enable" -a -n "$webapp" ]; then | ||||
|     urequire deploy | ||||
|     deploy_setconf "$deploy_confname" | ||||
|     if deploy_loadconf; then | ||||
|         setxx waname=abspath "$webapp" // basename -- | ||||
|         if eval "$(deploy_query -v host,wamap,protect DEST webapp rtoinst_deploy "$deploy_profile" shell "$waname")"; then | ||||
|             msg="$waname: cette webapp sera déployée vers les hôtes suivants: | ||||
| $(array_to_lines host "" "    ")" | ||||
|             if [ -n "$wamap" -o -n "$protect" ]; then | ||||
|                 msg="$msg | ||||
| avec le(s) paramètre(s) suivant(s):" | ||||
|                 [ -n "$wamap" ] && msg="$msg | ||||
|     --wamap $(qval "$wamap")" | ||||
|                 [ -n "$protect" ] && msg="$msg | ||||
|     --protect $(qval "$protect")" | ||||
|             fi | ||||
|             check_interaction -c && einfo "$msg" | ||||
|             ask_any "Voulez-vous continuer?" Oq || die | ||||
|             array_copy hosts host | ||||
|             [ -n "$wamap" ] && array_add toinst_options --wamap "$wamap" | ||||
|             [ -n "$protect" ] && array_add toinst_options --protect "$protect" | ||||
|             if [ -n "$confirm_webapp" ]; then | ||||
|                 confirm_webapp= | ||||
|                 set -- "$webapp" "$@" | ||||
|             fi | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| if [ -n "$confirm_webapp" ]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de toinst) | ||||
|     read_value "Veuillez entrer la webapp à déployer" webapp "$webapp" O | ||||
|     set -- "$webapp" "$@" | ||||
| fi | ||||
| 
 | ||||
| array_isempty hosts && read_value "Entrez une liste d'hôtes séparés par ':'" hosts "localhost" | ||||
| fix_hosts | ||||
| 
 | ||||
| ## Création de l'archive | ||||
| etitle "Création du répertoire de travail" | ||||
| ac_set_tmpdir workdir | ||||
| webapps=() | ||||
| while [ $# -gt 0 ]; do | ||||
|     if [ "$1" == "--" ]; then | ||||
|         # début des options de toinst | ||||
|         shift | ||||
|         break | ||||
|     elif [[ "$1" == -* ]]; then | ||||
|         # début des options de toinst | ||||
|         break | ||||
|     fi | ||||
| 
 | ||||
|     osrc="$1"; shift | ||||
|     setx src=abspath "$osrc" | ||||
|     setx srcname=basename -- "$src" | ||||
|     if [ -f "$src" ] && is_archive "$src"; then | ||||
|         setx waname=get_archive_appname "$src" | ||||
|         estep "$(ppath "$src") --> $waname" | ||||
|         wadir="$workdir/$waname" | ||||
|         mkdir "$wadir" | ||||
|         extract_archive "$src" "$wadir" || die | ||||
|         src="$wadir" | ||||
|     elif [ -d "$src" ]; then | ||||
|         estep "$(ppath2 "$src")" | ||||
|         cp_R "$src" "$workdir/$srcname" || die | ||||
|     elif [ -e "$src" ]; then | ||||
|         die "$osrc: fichier invalide" | ||||
|     else | ||||
|         die "$osrc: fichier ou répertoire introuvable" | ||||
|     fi | ||||
| 
 | ||||
|     array_add webapps "$srcname" | ||||
| done | ||||
| 
 | ||||
| estep "Copie de l'environnement de déploiement" | ||||
| mkdir "$workdir/lib" | ||||
| ulibsync "$workdir/lib" | ||||
| cp "$scriptdir/toinst" "$workdir" | ||||
| chmod +x "$workdir/toinst" | ||||
| 
 | ||||
| eend | ||||
| 
 | ||||
| ac_set_tmpfile archive | ||||
| archivename="$(basename "$archive")" | ||||
| 
 | ||||
| etitle "Création de l'archive pour le déploiement" | ||||
| "$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./toinst --is-tmpdir || die | ||||
| eend | ||||
| 
 | ||||
| ## Déploiement | ||||
| 
 | ||||
| # sur l'hôte distant, ne rendre non interactif qu'à partir de -yy | ||||
| rinteraction=$__interaction | ||||
| [ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1)) | ||||
| 
 | ||||
| for host in "${hosts[@]}"; do | ||||
|     if [ "$host" == "localhost" ]; then | ||||
|         etitle "Déploiement sur l'hôte local" | ||||
|         "$archive" ${tmproot:+--tmproot "$tmproot"} -- "${webapps[@]}" "$@" "${toinst_options[@]}" | ||||
|         eend | ||||
|     else | ||||
|         splituserhost "$host" user host | ||||
|         [ -n "$user" ] || user=root | ||||
| 
 | ||||
|         etitle "Déploiement sur $user@$host" | ||||
| 
 | ||||
|         estep "Copie de l'archive" | ||||
|         scp -S "$SSH" "$archive" "$user@$host:" || die | ||||
| 
 | ||||
|         estep "Lancement du script de déploiement" | ||||
|         "$SSH" -qt "$user@$host" "\ | ||||
| __interaction=$rinteraction | ||||
| __estack=$(qval "$__estack") | ||||
| __tlevel=$(qval "$__tlevel") | ||||
| export __interaction __estack __tlevel | ||||
| ${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG | ||||
| }$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- "${webapps[@]}" "$@" "${toinst_options[@]}")" | ||||
| 
 | ||||
|         eend | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										98
									
								
								ruinst
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								ruinst
									
									
									
									
									
								
							| @ -56,37 +56,11 @@ OPTIONS | ||||
|         Par défaut, si aucun hôte n'est spécifié, la configuration locale de | ||||
|         déploiement est interrogée pour avoir cette information. | ||||
|     -c, --deploy-config CONFNAME | ||||
|         Cette option permet de spécifier le nom de la configuration à utiliser | ||||
|         pour effectuer la requête. Par défaut, utiliser le nom 'ruinst'" | ||||
|         Cette option permet de spécifier le nom de la configuration locale de | ||||
|         déploiement à utiliser pour effectuer la requête. Par défaut, utiliser | ||||
|         le nom 'ruinst'" | ||||
| } | ||||
| 
 | ||||
| set_defaults pubkeys | ||||
| 
 | ||||
| action=deploy | ||||
| confuser= | ||||
| uses_su= | ||||
| tmproot= | ||||
| SSH= | ||||
| force_make_archive= | ||||
| hosts=() | ||||
| deploy_enable=1 | ||||
| deploy_confname=ruinst | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -C,--configure-user action=configure \ | ||||
|     --configure: '$set@ confuser;action=configure' \ | ||||
|     --uses-su uses_su=1 \ | ||||
|     -T:,--tmproot: tmproot= \ | ||||
|     -S:,--ssh: SSH= \ | ||||
|     --force-make-archive force_make_archive=1 \ | ||||
|     -h:,-H:,--host: hosts \ | ||||
|     --deploy deploy_enable=1 \ | ||||
|     --no-deploy deploy_enable= \ | ||||
|     -c:,--deploy-config deploy_confname= \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| : "${SSH:=ssh}" | ||||
| 
 | ||||
| __PARSED_HOSTS=() | ||||
| __PARSED_FILES=() | ||||
| function parse_hostsfile() { | ||||
| @ -150,6 +124,33 @@ function fix_hosts() { | ||||
|     array_map hosts __dot_is_localhost | ||||
| } | ||||
| 
 | ||||
| set_defaults pubkeys | ||||
| 
 | ||||
| action=deploy | ||||
| confuser= | ||||
| uses_su= | ||||
| tmproot= | ||||
| SSH= | ||||
| force_make_archive= | ||||
| hosts=() | ||||
| deploy_enable=1 | ||||
| deploy_confname=ruinst | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -C,--configure-user action=configure \ | ||||
|     --configure: '$set@ confuser;action=configure' \ | ||||
|     --uses-su uses_su=1 \ | ||||
|     -T:,--tmproot: tmproot= \ | ||||
|     -S:,--ssh: SSH= \ | ||||
|     --force-make-archive force_make_archive=1 \ | ||||
|     -h:,-H:,--host: hosts \ | ||||
|     --deploy deploy_enable=1 \ | ||||
|     --no-deploy deploy_enable= \ | ||||
|     -c:,--deploy-config deploy_confname= \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| : "${SSH:=ssh}" | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Configuration de l'accès par clé aux hôtes | ||||
| 
 | ||||
| @ -218,36 +219,43 @@ fi | ||||
| ################################################################################ | ||||
| # Déploiement | ||||
| 
 | ||||
| make_archive= | ||||
| 
 | ||||
| ## Répertoire à déployer | ||||
| src="$1" | ||||
| if [ -z "$src" ] || [[ "$src" == -* ]]; then | ||||
| ## Répertoires à déployer et hôtes sur lesquels faire le déploiement | ||||
| confirm_src= | ||||
| if [ $# -eq 0 ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de uinst) | ||||
|     read_value "Entrez le répertoire à déployer" src "." | ||||
|     src=. | ||||
|     confirm_src=1 | ||||
| else | ||||
|     # Enlever le répertoire à déployer. Le reste est pour uinst | ||||
|     src="$1" | ||||
|     shift | ||||
| fi | ||||
| 
 | ||||
| ## Hôtes sur lesquels faire le déploiement | ||||
| if array_isempty hosts && [ -n "$deploy_enable" ]; then | ||||
| if array_isempty hosts && [ -n "$deploy_enable" -a -n "$src" ]; then | ||||
|     urequire deploy | ||||
|     deploy_setconf "$deploy_confname" | ||||
|     if deploy_loadconf; then | ||||
|         setxx module=abspath "$src" // basename -- | ||||
|         if eval "$(deploy_query -v host DEST module ruinst_deploy "" shell "$module")"; then | ||||
|             check_interaction -c && einfo "Ce module sera déployé vers les hôtes suivants: | ||||
|         setxx srcname=abspath "$src" // basename -- | ||||
|         if eval "$(deploy_query -v host DEST module ruinst_deploy "" shell "$srcname")"; then | ||||
|             check_interaction -c && einfo "$srcname: ce module sera déployé vers les hôtes suivants: | ||||
| $(array_to_lines host "" "    ")" | ||||
|             ask_any "Voulez-vous continuer?" Oq || die | ||||
|             array_copy hosts host | ||||
|             confirm_src= | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| if [ -n "$confirm_src" ]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de uinst) | ||||
|     read_value "Entrez le répertoire à déployer" src "$src" O | ||||
| fi | ||||
| 
 | ||||
| array_isempty hosts && read_value "Entrez une liste d'hôtes séparés par ':'" hosts "localhost" | ||||
| fix_hosts | ||||
| 
 | ||||
| ## Création de l'archive? | ||||
| make_archive= | ||||
| if [ -n "$force_make_archive" ]; then | ||||
|     make_archive=1 | ||||
| else | ||||
| @ -265,13 +273,14 @@ if [ -n "$make_archive" ]; then | ||||
|     ac_set_tmpfile archive | ||||
|     archivename="$(basename "$archive")" | ||||
| 
 | ||||
|     etitle "Création de l'archive pour le déploiement" \ | ||||
|         "$scriptdir/mkusfx" --tmp-archive --self-contained -o "$archive" "$src" || die | ||||
|     etitle "Création de l'archive pour le déploiement" | ||||
|     "$scriptdir/mkusfx" --tmp-archive --self-contained -o "$archive" "$src" || die | ||||
|     eend | ||||
| fi | ||||
| 
 | ||||
| ## Déploiement | ||||
| 
 | ||||
| # sur l'hôte distant, ne rendre interactif qu'à partir de -yy | ||||
| # sur l'hôte distant, ne rendre non interactif qu'à partir de -yy | ||||
| rinteraction=$__interaction | ||||
| [ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1)) | ||||
| 
 | ||||
| @ -289,8 +298,10 @@ for host in "${hosts[@]}"; do | ||||
|         [ -n "$user" ] || user=root | ||||
| 
 | ||||
|         etitle -s "Déploiement sur $user@$host" | ||||
| 
 | ||||
|         estep "Copie de l'archive" | ||||
|         scp -S "$SSH" "$archive" "$user@$host:" || die | ||||
| 
 | ||||
|         estep "Lancement du script de déploiement" | ||||
|         "$SSH" -qt "$user@$host" "\ | ||||
| __interaction=$rinteraction | ||||
| @ -299,6 +310,7 @@ __tlevel=$(qval "$__tlevel") | ||||
| export __interaction __estack __tlevel | ||||
| ${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG | ||||
| }$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")" | ||||
| 
 | ||||
|         eend | ||||
|     fi | ||||
| done | ||||
|  | ||||
							
								
								
									
										292
									
								
								rwoinst
									
									
									
									
									
								
							
							
						
						
									
										292
									
								
								rwoinst
									
									
									
									
									
								
							| @ -9,21 +9,11 @@ function display_help() { | ||||
| USAGE | ||||
|     $scriptname [-H host] [-T tmproot] <file|archive|dir>... [-- options de woinst] | ||||
| 
 | ||||
| note: à cause d'une limitation de makeself, les options de toinst ne devraient | ||||
| pas contenir d'espaces ni de caractères spéciaux. L'échappement de ces | ||||
| caractères n'est pas garanti. | ||||
| 
 | ||||
| OPTIONS | ||||
|     -C, --configure-user | ||||
|     --configure USER [--uses-su] | ||||
|         Ne pas faire le déploiement. Configurer uniquement la connexion par clé | ||||
|         sur les hôtes distants spécifiés pour le user spécifié. Il faut pouvoir | ||||
|         se connecter par mot de passe pour configurer la connexion par clé. | ||||
|         Si l'on veut configurer la connexion par clé pour le user root, mais que | ||||
|         ce n'est pas possible de se connecter par mot de passe avec le user root | ||||
|         sur l'hôte distant, et qu'il existe un user sudoer sur l'hôte distant, | ||||
|         il est possible de faire la configuration avec '--configure root'. La | ||||
|         commande serait alors | ||||
|             $scriptname -H user@host --configure root | ||||
|         Si l'hôte distant n'a pas sudo ou si sudo n'est pas configuré, il faut | ||||
|         rajouter l'option --uses-su, e.g: | ||||
|             $scriptname -h user@host --configure root --uses-su | ||||
|     -T, --tmproot TMPROOT | ||||
|         Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple | ||||
|         /var/tmp. Cette option est utile pour les vservers, qui ont par défaut | ||||
| @ -32,7 +22,6 @@ OPTIONS | ||||
|         Spécifier le programme à utiliser pour la connection par ssh. | ||||
|     -h, --host hosts | ||||
|     -h, --host @hostsfile | ||||
|     -H host | ||||
|         Spécifier un ou plusieurs hôtes sur lequels faire le déploiement. Pour | ||||
|         spécifier plusieurs hôtes, il est possible d'utiliser plusieurs fois | ||||
|         l'option -h, ou spécifier en une seule fois plusieurs hôtes en les | ||||
| @ -45,6 +34,17 @@ OPTIONS | ||||
|         user@host, e.g -h user@host | ||||
|         La forme @hostsfile permet de lire la liste des hôtes depuis le fichier | ||||
|         hostsfile, à raison d'un hôte par ligne. | ||||
|     -w, -W, --whost host[:htdocs] | ||||
|         Comme --host, mais pour le déploiement des resources web. Contrairement | ||||
|         à --host, un seul hôte peut être spécifié par occurence de l'option, | ||||
|         pour permettre de spécifier éventuellement le répertoire vers lequel | ||||
|         copier les resources web. Ainsi, les deux commandes suivantes sont | ||||
|         équivalentes: | ||||
|             rwoinst -h host.tld -- -W HTDOCSDIR=HTDOCSBASE/wo | ||||
|             rwoinst -w host.tld:HTDOCSBASE/wo | ||||
|         Il est possible de spécifier en une seule invocation --host et --whost | ||||
|         pour déployer l'application sur un hôte et les resources web sur un | ||||
|         autre. | ||||
|     --deploy | ||||
|     --no-deploy | ||||
|         Autoriser (respectivement interdire) l'utilisation de la configuration | ||||
| @ -54,34 +54,12 @@ OPTIONS | ||||
|         déploiement est interrogée pour avoir cette information. | ||||
|     -c, --deploy-config CONFNAME | ||||
|         Cette option permet de spécifier le nom de la configuration à utiliser | ||||
|         pour effectuer la requête. Par défaut, utiliser le nom 'rwoinst'" | ||||
|         pour effectuer la requête. Par défaut, utiliser le nom 'rwoinst' | ||||
|     -p, --deploy-profile PROFILE | ||||
|         Spécifier le profil à utiliser pour l'interrogation de la configuration | ||||
|         locale de déploiement. Par défaut, aucun profil n'est sélectionné." | ||||
| } | ||||
| 
 | ||||
| set_defaults pubkeys | ||||
| 
 | ||||
| action=deploy | ||||
| confuser= | ||||
| uses_su= | ||||
| tmproot= | ||||
| SSH= | ||||
| hosts=() | ||||
| deploy_enable=1 | ||||
| deploy_confname=rwoinst | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -C,--configure-user action=configure \ | ||||
|     --configure: '$set@ confuser;action=configure' \ | ||||
|     --uses-su uses_su=1 \ | ||||
|     -T:,--tmproot: tmproot= \ | ||||
|     -S:,--ssh: SSH= \ | ||||
|     -h:,-H:,--host: hosts \ | ||||
|     --deploy deploy_enable=1 \ | ||||
|     --no-deploy deploy_enable= \ | ||||
|     -c:,--deploy-config deploy_confname= \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| SSH="${SSH:-ssh}" | ||||
| 
 | ||||
| __PARSED_HOSTS=() | ||||
| __PARSED_FILES=() | ||||
| function parse_hostsfile() { | ||||
| @ -145,47 +123,149 @@ function fix_hosts() { | ||||
|     array_map hosts __dot_is_localhost | ||||
| } | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Configuration de l'accès par clé aux hôtes | ||||
| function deploy_to() { | ||||
|     local archive="$1" host="$2" tmproot="$3" | ||||
|     shift; shift; shift | ||||
| 
 | ||||
| if [ "$action" == "configure" ]; then | ||||
|     args=(${confuser:+--configure "$confuser"} ${uses_su:+--uses-su} -S "$SSH") | ||||
|     for host in "${hosts[@]}"; do | ||||
|         args=("${args[@]}" -H "$host") | ||||
|     done | ||||
|     exec "$scriptdir/ruinst" -C "${args[@]}" | ||||
|     local r= | ||||
|     if [ "$host" == "localhost" ]; then | ||||
|         etitle "Sur l'hôte local" | ||||
|         "$archive" ${tmproot:+--tmproot "$tmproot"} -- "$@" || r=1 | ||||
|         eend | ||||
|     else | ||||
|         local user | ||||
|         local archivename="$(basename "$archive")" | ||||
| 
 | ||||
|         splituserhost "$host" user host | ||||
|         [ -n "$user" ] || user=root | ||||
| 
 | ||||
|         # sur l'hôte distant, ne rendre non interactif qu'à partir de -yy | ||||
|         rinteraction=$__interaction | ||||
|         [ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1)) | ||||
| 
 | ||||
|         etitle "Vers $user@$host" | ||||
| 
 | ||||
|         estep "Copie de l'archive" | ||||
|         scp -S "$SSH" "$archive" "$user@$host:" || r=1 | ||||
| 
 | ||||
|         if [ -z "$r" ]; then | ||||
|             estep "Lancement du script de déploiement" | ||||
|             "$SSH" -qt "$user@$host" "\ | ||||
| __interaction=$rinteraction | ||||
| __estack=$(qval "$__estack") | ||||
| __tlevel=$(qval "$__tlevel") | ||||
| export __interaction __estack __tlevel | ||||
| ${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG | ||||
| }$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")" || r=1 | ||||
|         fi | ||||
| 
 | ||||
|         eend | ||||
|     fi | ||||
|     return ${r:-0} | ||||
| } | ||||
| 
 | ||||
| action=deploy | ||||
| tmproot= | ||||
| SSH= | ||||
| hosts=() | ||||
| whosts=() | ||||
| deploy_enable=1 | ||||
| deploy_confname=rwoinst | ||||
| deploy_profile= | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -T:,--tmproot: tmproot= \ | ||||
|     -S:,--ssh: SSH= \ | ||||
|     -h:,-H:,--host: hosts \ | ||||
|     -w:,-W:,--whost: whosts \ | ||||
|     --deploy deploy_enable=1 \ | ||||
|     --no-deploy deploy_enable= \ | ||||
|     -c:,--deploy-config deploy_confname= \ | ||||
|     -p:,--deploy-profile: deploy_profile= \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| : "${SSH:=ssh}" | ||||
| 
 | ||||
| ## Bundle à déployer et hôtes sur lesquels faire le déploiement | ||||
| confirm_bundle= | ||||
| if [ $# -eq 0 ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst) | ||||
|     case "$(basename -- "$(pwd)")" in | ||||
|     *.woa|*.framework) bundle=.;; | ||||
|     *) bundle=;; | ||||
|     esac | ||||
|     confirm_bundle=1 | ||||
| else | ||||
|     bundle="$1" | ||||
| fi | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Déploiement | ||||
| 
 | ||||
| ## Bundle à déployer | ||||
| if [ -z "$1" ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de | ||||
|     # woinst) | ||||
|     die "Vous devez spécifier le bundle à déployer" | ||||
| fi | ||||
| 
 | ||||
| ## Hôtes sur lesquels faire le déploiement | ||||
| if array_isempty hosts && [ -n "$deploy_enable" ]; then | ||||
| woinst_options=() | ||||
| if array_isempty hosts && [ -n "$deploy_enable" -a -n "$bundle" ]; then | ||||
|     urequire deploy | ||||
|     deploy_setconf "$deploy_confname" | ||||
|     if deploy_loadconf; then | ||||
|         setxx wobundle=abspath "$1" // basename -- | ||||
|         if eval "$(deploy_query -v host DEST wobundle rwoinst_bundle "" shell "$wobundle")"; then | ||||
|             check_interaction -c && einfo "Ce bundle sera déployé vers les hôtes suivants: | ||||
| $(array_to_lines host "" "    ")" | ||||
|         setxx bundlename=abspath "$bundle" // basename -- | ||||
|         host=(); bounce=; notag=; exec=; dbconfig=; dbconfigmap= | ||||
|         if eval "$(deploy_query -v host,bounce,notag,exec,dbconfig,dbconfigmap DEST wobundle rwoinst_bundle "$deploy_profile" shell "$bundlename")"; then | ||||
|             array_copy deploy_hosts host | ||||
|             deploy_options=() | ||||
|             [ -n "$bounce" ] && array_add deploy_options -b | ||||
|             [ -n "$notag" ] && array_add deploy_options -n | ||||
|             if [ -n "$exec" ]; then | ||||
|                 for x in "${exec[@]}"; do | ||||
|                     array_add deploy_options -x "$x" | ||||
|                 done | ||||
|             fi | ||||
|             [ -n "$dbconfig" ] && array_add deploy_options -d "$dbconfig" | ||||
|             if [ -n "$dbconfigmap" ]; then | ||||
|                 for m in "${dbconfigmap[@]}"; do | ||||
|                     array_add deploy_options -m "$m" | ||||
|                 done | ||||
|             fi | ||||
|             deploy_whosts=() | ||||
|             host=(); destdir= | ||||
|             if eval "$(deploy_query -v host,destdir DEST wobundle rwoinst_webres "$deploy_profile" shell "$bundlename")"; then | ||||
|                 for wh in "${host[@]}"; do | ||||
|                     array_add deploy_whosts "$wh:$destdir" | ||||
|                 done | ||||
|             fi | ||||
|             msg="$bundlename: ce bundle sera déployé vers les hôtes suivants: | ||||
| $(array_to_lines deploy_hosts "" "    ")" | ||||
|             if [ ${#deploy_whosts[*]} -gt 0 -o ${#deploy_options[*]} -gt 0 ]; then | ||||
|                 msg="$msg | ||||
| avec le(s) paramètre(s) suivant(s):" | ||||
|                 [ ${#deploy_whosts[*]} -gt 0 ] && msg="$msg | ||||
| $(array_to_lines deploy_whosts "" "    --whost ")" | ||||
|                 [ ${#deploy_options[*]} -gt 0 ] && msg="$msg | ||||
|     $(qvals "${deploy_options[@]}")" | ||||
|             fi | ||||
|             check_interaction -c && einfo "$msg" | ||||
|             ask_any "Voulez-vous continuer?" Oq || die | ||||
|             array_copy hosts host | ||||
|             array_extend hosts deploy_hosts | ||||
|             array_extend woinst_options deploy_options | ||||
|             array_extend whosts deploy_whosts | ||||
|             if [ -n "$confirm_bundle" ]; then | ||||
|                 confirm_bundle= | ||||
|                 set -- "$bundle" "$@" | ||||
|             fi | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| if [ -n "$confirm_bundle" ]; then | ||||
|     # pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst) | ||||
|     read_value "Veuillez entrer la bundle à déployer" bundle "$bundle" O | ||||
|     set -- "$bundle" "$@" | ||||
| fi | ||||
| 
 | ||||
| array_isempty hosts && read_value "Entrez une liste d'hôtes séparés par ':'" hosts "localhost" | ||||
| fix_hosts | ||||
| 
 | ||||
| ## Création de l'archive | ||||
| etitle -s "Création du répertoire de travail" | ||||
| 
 | ||||
| etitle "Création du répertoire de travail" | ||||
| ac_set_tmpdir workdir | ||||
| 
 | ||||
| bundles=() | ||||
| while [ -n "$1" ]; do | ||||
|     if [ "$1" == "--" ]; then | ||||
| @ -203,6 +283,19 @@ while [ -n "$1" ]; do | ||||
|         cp_R "$src" "$workdir" || die | ||||
|     elif [ -d "$src" ]; then | ||||
|         src="$(abspath "$src")" | ||||
|         setx srcname=basename -- "$src" | ||||
|         case "$src" in | ||||
|         *.woa|*.framework) ;; | ||||
|         *) # support projet maven | ||||
|             if [ ! -f "$src/pom.xml" ]; then | ||||
|                 : # non, pas un projet maven | ||||
|             elif [ -d "$src/target/$srcname.woa" ]; then | ||||
|                 src="$src/target/$srcname.woa" | ||||
|             elif [ -d "$src/target/$srcname.framework" ]; then | ||||
|                 src="$src/target/$srcname.framework" | ||||
|             fi | ||||
|             ;; | ||||
|         esac | ||||
|         if endswith "$src" .framework; then | ||||
|             is_wofwkdir "$src" || die "Framework invalide: $(ppath "$src")" | ||||
|         elif endswith "$src" .woa; then | ||||
| @ -210,7 +303,7 @@ while [ -n "$1" ]; do | ||||
|         else | ||||
|             die "N'est pas un bundle valide: $(ppath "$src")" | ||||
|         fi | ||||
|         estep "$(ppath "$src")" | ||||
|         estep "$(ppath2 "$src")" | ||||
|         cp_R "$src" "$workdir" || die | ||||
|     else | ||||
|         die "Fichier ou répertoire introuvable: $src" | ||||
| @ -221,55 +314,34 @@ while [ -n "$1" ]; do | ||||
| done | ||||
| 
 | ||||
| estep "Copie de l'environnement de déploiement" | ||||
| ulibsync "$workdir" | ||||
| echo '#!/bin/sh | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| if . `dirname "$0"`/ulib/ulibsh; then | ||||
|     urequire DEFAULTS woinst | ||||
| else | ||||
|     exit 1 | ||||
| fi | ||||
| OENC="$UTF8" | ||||
| woinst "$@"' >"$workdir/woinst" | ||||
| chmod +x "$workdir/woinst" | ||||
| mkdir "$workdir/lib" | ||||
| ulibsync "$workdir/lib" | ||||
| cp "$scriptdir/woinst.sh" "$workdir" | ||||
| chmod +x "$workdir/woinst.sh" | ||||
| 
 | ||||
| eend | ||||
| 
 | ||||
| etitle "Création de l'archive pour le déploiement" | ||||
| ac_set_tmpfile archive | ||||
| archivename="$(basename "$archive")" | ||||
| 
 | ||||
| etitle "Création de l'archive pour le déploiement" \ | ||||
|     "$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./woinst --is-tmpdir "${bundles[@]}" || die | ||||
| "$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./woinst.sh --is-tmpdir "${bundles[@]}" || die | ||||
| 
 | ||||
| eend | ||||
| 
 | ||||
| ## Déploiement | ||||
| 
 | ||||
| # sur l'hôte distant, ne rendre interactif qu'à partir de -yy | ||||
| rinteraction=$__interaction | ||||
| [ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1)) | ||||
| 
 | ||||
| etitle "Déploiement des bundles" | ||||
| for host in "${hosts[@]}"; do | ||||
|     if [ "$host" == "localhost" ]; then | ||||
|         etitle "Déploiement sur l'hôte local" \ | ||||
|             "$archive" ${tmproot:+--tmproot "$tmproot"} -- "$@" | ||||
|     else | ||||
|         if [[ "$host" == *@* ]]; then | ||||
|             user="${host%%@*}" | ||||
|             host="${host#*@}" | ||||
|         else | ||||
|             user=root | ||||
|         fi | ||||
| 
 | ||||
|         etitle -s "Déploiement sur $user@$host" | ||||
|         estep "Copie de l'archive" | ||||
|         scp -S "$SSH" "$archive" "$user@$host:" || die | ||||
|         estep "Lancement du script de déploiement" | ||||
|         "$SSH" -qt "$user@$host" "\ | ||||
| __interaction=$rinteraction | ||||
| __estack=$(qval "$__estack") | ||||
| __tlevel=$(qval "$__tlevel") | ||||
| export __interaction __estack __tlevel | ||||
| ${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG | ||||
| }$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")" | ||||
|         eend | ||||
|     fi | ||||
|     deploy_to "$archive" "$host" "$tmproot" "$@" "${woinst_options[@]}" || die | ||||
| done | ||||
| eend | ||||
| 
 | ||||
| if [ ${#whosts[*]} -gt 0 ]; then | ||||
|     etitle "Déploiement des resources web" | ||||
|     for hostdestdir in "${whosts[@]}"; do | ||||
|         splitpair "$hostdestdir" host destdir | ||||
|         deploy_to "$archive" "$host" "$tmproot" \ | ||||
|                   -y -W ${destdir:+HTDOCSDIR="$destdir"} "$@" "${woinst_options[@]}" || die | ||||
|     done | ||||
|     eend | ||||
| fi | ||||
|  | ||||
							
								
								
									
										171
									
								
								tailor.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										171
									
								
								tailor.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,171 @@ | ||||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| 
 | ||||
| u"""Afficher les lignes d'un fichier en mettant en surbrillance certains patterns""" | ||||
| 
 | ||||
| import sys, subprocess, re | ||||
| from collections import OrderedDict | ||||
| 
 | ||||
| def bluef(line, *ignored): return '\x1B[34m%s\x1B[0m' % line | ||||
| def greenf(line, *ignored): return '\x1B[32m%s\x1B[0m' % line | ||||
| def yellowf(line, *ignored): return '\x1B[33m%s\x1B[0m' % line | ||||
| def redf(line, *ignored): return '\x1B[31m%s\x1B[0m' % line | ||||
| def nonef(line, *ignored): return re.sub('\x1B\[.*?m', '', line) | ||||
| 
 | ||||
| DEFAULT_PATTERNS = OrderedDict([ | ||||
|     (r'(?i)error', redf), | ||||
|     (r'(?i)warn(ing)?', yellowf), | ||||
|     (r'(?i)info', bluef), | ||||
|     (None, nonef), | ||||
| ]) | ||||
| FORMATS = OrderedDict([ | ||||
|     ('blue', bluef), | ||||
|     ('green', greenf), | ||||
|     ('yellow', yellowf), | ||||
|     ('red', redf), | ||||
|     ('none', nonef), | ||||
| ]) | ||||
| FORMAT_ALIASES = { | ||||
|     'b': 'blue', | ||||
|     'g': 'green', | ||||
|     'y': 'yellow', | ||||
|     'r': 'red', | ||||
|     '': 'none', | ||||
| } | ||||
| 
 | ||||
| def strip_nl(s): | ||||
|     if s is None: return None | ||||
|     elif s.endswith("\r\n"): s = s[:-2] | ||||
|     elif s.endswith("\n"): s = s[:-1] | ||||
|     elif s.endswith("\r"): s = s[:-1] | ||||
|     return s | ||||
| 
 | ||||
| def run_tailor(inputfile=None, follow=False, patterns=None): | ||||
|     if inputfile is None or not follow: | ||||
|         if inputfile is None: | ||||
|             inf = sys.stdin | ||||
|             close = False | ||||
|         else: | ||||
|             inf = open(inputfile, 'rb') | ||||
|             close = True | ||||
|         def next_line(): | ||||
|             try: | ||||
|                 while True: | ||||
|                     try: line = inf.readline() | ||||
|                     except: break | ||||
|                     if line == '': break | ||||
|                     yield line | ||||
|             finally: | ||||
|                 if close: inf.close() | ||||
|     else: | ||||
|         def next_line(): | ||||
|             p = subprocess.Popen( | ||||
|                 ['tail', '-f', inputfile], | ||||
|                 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | ||||
|             while True: | ||||
|                 try: line = p.stdout.readline() | ||||
|                 except: break | ||||
|                 if line == '': break | ||||
|                 yield line | ||||
|     if patterns is None: patterns = DEFAULT_PATTERNS | ||||
| 
 | ||||
|     for line in next_line(): | ||||
|         line = nonef(strip_nl(line)) | ||||
|         func = False | ||||
|         mo = None | ||||
|         for p, f in patterns.items(): | ||||
|             if p is None: | ||||
|                 func = f | ||||
|                 mo = None | ||||
|                 break | ||||
|             mo = re.search(p, line) | ||||
|             if mo is not None: | ||||
|                 func = f | ||||
|                 break | ||||
|         if func is not False: | ||||
|             line = func(line, mo) | ||||
|             sys.stdout.write(line) | ||||
|             sys.stdout.write('\n') | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     from argparse import ArgumentParser, HelpFormatter | ||||
|     if sys.argv[1:2] == ['--compat']: | ||||
|         # Avec l'argument --compat, désactiver la classe FancyHelpFormatter qui | ||||
|         # se base sur une API non documentée | ||||
|         sys.argv = sys.argv[0:1] + sys.argv[2:] | ||||
|         FancyHelpFormatter = HelpFormatter | ||||
|     else: | ||||
|         class FancyHelpFormatter(HelpFormatter): | ||||
|             """Comme HelpFormatter, mais ne touche pas aux lignes qui commencent par les | ||||
|             caractères '>>>'. Cela permet de mixer du texte formaté et du texte non | ||||
|             formaté. | ||||
|             """ | ||||
|             def _fill_text(self, text, width, indent): | ||||
|                 return ''.join([indent + line for line in text.splitlines(True)]) | ||||
|             def _split_lines(self, text, width): | ||||
|                 lines = [''] | ||||
|                 for line in text.splitlines(): | ||||
|                     if line.startswith('>>>'): | ||||
|                         lines.append(line) | ||||
|                         lines.append('') | ||||
|                     else: | ||||
|                         lines[-1] += '\n' + line | ||||
|                 lines = filter(None, lines) | ||||
|                 texts = [] | ||||
|                 for line in lines: | ||||
|                     if line.startswith('>>>'): | ||||
|                         texts.append(line[3:]) | ||||
|                     else: | ||||
|                         texts.extend(super(FancyHelpFormatter, self)._split_lines(line, width)) | ||||
|                 return texts | ||||
|     AP = ArgumentParser( | ||||
|         usage=u"%(prog)s [-f] [INPUTFILE]", | ||||
|         description=__doc__, | ||||
|         formatter_class=FancyHelpFormatter, | ||||
|     ) | ||||
|     AP.set_defaults(inputfile=None, follow=False, patterns=None, defaults=True) | ||||
|     pattern_help = u"""\ | ||||
| Ajouter une spécification de pattern et le format dans lequel il doit être affiché. | ||||
| Le format par défaut est red. Les formats valides sont: | ||||
| >>>    %(formats)s""" % { | ||||
|     'formats': ', '.join(FORMATS.keys()), | ||||
| } | ||||
|     AP.add_argument('-e', '--pattern', action='append', dest='patterns', metavar='PATTERN:FORMAT', | ||||
|                     help=pattern_help) | ||||
|     default_patterns = [u"%s:%s" % (p or '', f.__name__[:-1]) for (p, f) in DEFAULT_PATTERNS.items()] | ||||
|     no_defaults_help = u"""\ | ||||
| Ne pas ajouter les patterns par défaut. Sans cette option, les patterns par défaut sont: | ||||
| %(default_patterns)s""" % { | ||||
|     'default_patterns': '\n'.join([u">>>    %s" % pattern for pattern in default_patterns]), | ||||
| } | ||||
|     AP.add_argument('-z', '--no-defaults', action='store_false', dest='defaults', | ||||
|                     help=no_defaults_help) | ||||
|     AP.add_argument('-f', '--follow', action='store_true', dest='follow', | ||||
|                     help=u"Suivre le contenu du fichier spécifié") | ||||
|     AP.add_argument('inputfile', metavar='INPUTFILE', nargs='?', | ||||
|                     help=u"Fichier qu'il faut afficher ou dont il faut suivre le contenu") | ||||
|     o = AP.parse_args() | ||||
| 
 | ||||
|     if o.patterns is None: | ||||
|         patterns = DEFAULT_PATTERNS | ||||
|     else: | ||||
|         patterns = OrderedDict() | ||||
|         for pf in o.patterns: | ||||
|             mo = re.match('(.*):([a-zA-Z]*)$', pf) | ||||
|             if mo is not None: | ||||
|                 p = mo.group(1) | ||||
|                 of = mo.group(2) | ||||
|             else: | ||||
|                 p = pf | ||||
|                 of = 'red' | ||||
|             if p == '': p = None | ||||
|             f = of.lower() | ||||
|             f = FORMAT_ALIASES.get(f, f) | ||||
|             if f not in FORMATS: | ||||
|                 raise ValueError("%s: format invalide" % of) | ||||
|             patterns[p] = FORMATS[f] | ||||
|         if o.defaults: | ||||
|             for p, f in DEFAULT_PATTERNS.items(): | ||||
|                 patterns.setdefault(p, f) | ||||
| 
 | ||||
|     run_tailor(o.inputfile, o.follow, patterns) | ||||
							
								
								
									
										663
									
								
								toinst
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										663
									
								
								toinst
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,663 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS xmlsupport | ||||
| 
 | ||||
| function display_help() { | ||||
|     uecho "$scriptname: Déployer une ou plusieurs webapps vers Tomcat | ||||
| 
 | ||||
| USAGE | ||||
|     $scriptname [options] <archive|dir>... | ||||
| 
 | ||||
| OPTIONS | ||||
|     -c, --config CONFIG | ||||
|         Spécifier un fichier de configuration qui contient les informations | ||||
|         spécifiées par les options ci-dessous: TOMCAT_PROFILE, CATALINA_BASE, | ||||
|         TOMCAT_USER, TOMCAT_GROUP, TOMCAT_VERSION, MANAGER_URL, MANAGER_USER, | ||||
|         MANAGER_PASSWORD, WAMAP, BACKUP, RESTART | ||||
|     -C, --config-profile TOMCAT_PROFILE | ||||
|         Spécifier le profil de configuration à utiliser. Cette valeur détermine | ||||
|         la façon dont sont calculés CATALINA_BASE, TOMCAT_USER, TOMCAT_GROUP et | ||||
|         TOMCAT_VERSION. Les valeurs valides sont: | ||||
|         * debian:tomcatV | ||||
|             Tomcat installé par 'apt-get install tomcatV'. L'alias 'd:V' est | ||||
|             aussi supporté, e.g 'debian:tomcat7' ou 'd:8' | ||||
|         * runs:NAME | ||||
|             Tomcat installé par 'runs tomcat/V name=NAME'. Le suffixe NAME est | ||||
|             le nom de base des fichiers de tomcat. Pour spécifier le cas échéant | ||||
|             la version de Tomcat, il faut utiliser l'option -V ci-dessous. | ||||
|             L'alias NAME sans le préfixe runs: est supporté aussi. | ||||
|         Le profil par défaut est calculé comme suit: | ||||
|         * Si un répertoire de la forme /var/lib/tomcatV existe alors il s'agit | ||||
|           de debian:tomcatV. | ||||
|         * Si le lien /opt/tomcat --> /opt/apache-tomcat-V existe, vérifier | ||||
|           l'existence du script /etc/init.d/tomcatV. Si le script existe, alors | ||||
|           utiliser runs:tomcatV comme profil. Sinon, utiliser runs:tomcat. | ||||
|         * Sinon, aucun profil n'est sélectionné, et il faut spécifier | ||||
|           manuellement les options -d, -U, -G, -V | ||||
|     -d, --catalina-base CATALINA_BASE | ||||
|         Spécifier le répertoire de base des configurations de Tomcat. La valeur | ||||
|         par défaut est celle de CATALINA_HOME. Cette option n'a normalement pas | ||||
|         besoin d'être spécifiée. | ||||
|     -U, --tomcat-user TOMCAT_USER | ||||
|     -G, --tomcat-group TOMCAT_GROUP | ||||
|         Spécifier l'utilisateur et le groupe propriétaires des fichiers de | ||||
|         Tomcat. Ces options n'ont normalement pas besoin d'être spécifiées. | ||||
|     -V, --tomcat-version TOMCAT_VERSION | ||||
|         Spécifier la version de tomcat installée, e.g 8.0.37 pour une version | ||||
|         complète ou simplement 8 si on ne donne que la version majeure. | ||||
|         Cette option peut s'avérer nécessaire avec le profil runs:tomcat bien | ||||
|         que les meilleurs efforts soient faits pour détecter la valeur | ||||
|         effective. | ||||
|     -g, --manager-url MANAGER_URL | ||||
|         Spécifier l'url du manager, e.g http://localhost:8080/manager/text | ||||
|         Par défaut, le fichier server.xml est consulté pour connaitre sur quel | ||||
|         port écoute le serveur. | ||||
|     -u, --user MANAGER_USER | ||||
|     -p, --password MANAGER_PASSWORD | ||||
|         Spécifier le compte et le mot de passe à utiliser pour piloter le | ||||
|         manager Tomcat, notamment pour redémarrer l'application venant d'être | ||||
|         déployée. Ce compte doit avoir le rôle manager-script à partir de Tomcat | ||||
|         6.0.30, et le rôle manager-gui dans les version antérieurs. Par défaut, | ||||
|         le fichier tomcat-users.xml est consulté pour avoir cette information. | ||||
|     -m, --wamap WAMAPS | ||||
|         Ajouter un ou plusieurs mappings de la forme src:dest. Avec ce mapping, | ||||
|         la webapp src est déployée avec le nom dest. Plusieurs mappings peuvent | ||||
|         être spécifiés en les séparant par des virgules. Si src est mentionné | ||||
|         plusieurs fois, e.g src:dest1,src:dest2 alors la webapp src est déployée | ||||
|         plusieurs fois avec des noms distincts. | ||||
|     --exclude EXCLUDES | ||||
|     --replace-excludes EXCLUDES | ||||
|         Spécifier un ensemble de fichier à exclure de la source lors du | ||||
|         déploiement. La variante --replace-excludes permet de construire la | ||||
|         liste des fichiers à exclure depuis zéro. La liste par défaut est: | ||||
|             ${DEFAULT_EXCLUDES[*]} | ||||
|     --protect PROTECTS | ||||
|         Spécifier un ensemble de fichier à protéger dans la destination: ils ne | ||||
|         sont jamais écrasés par les fichiers sources. Cela permet de gérer des | ||||
|         applications qui écrivent des fichiers dans leur répertoire. | ||||
|     --rsync-option RSYNC_OPTIONS | ||||
|     --replace-rsync-options RSYNC_OPTIONS | ||||
|         Spécifier les options de rsync à utiliser pour le déploiement. La | ||||
|         variante --replace-rsync-options permet de construire la liste des | ||||
|         options depuis zéro. La liste par défaut est: | ||||
|             ${DEFAULT_RSYNC_OPTIONS[*]} | ||||
|     -b, --backup | ||||
|     --no-backup | ||||
|         Avant le déploiement du service numérique, faire (resp. ne pas faire) | ||||
|         une sauvegarde des fichiers actuellement déployés. | ||||
|     -B, --backup-only | ||||
|         Ne pas faire le déploiement. Faire uniquement la sauvegarde. | ||||
|     -n, --no-restart | ||||
|         Après le déploiement de la webapp, ne pas redémarrer l'application. | ||||
|     -r, --restart-only | ||||
|         Ne pas faire le déploiement. Redémarrer uniquement l'application. | ||||
|     --fake | ||||
|         Afficher simplement ce qui serait fait. Ne pas le faire réellement. | ||||
|     --config-template | ||||
|         Créer un modèle de configuration dans le répertoire des webapp | ||||
|         spécifiées. Si aucune webapp n'est spécifiée, créer le fichier dans le | ||||
|         répertoire courant." | ||||
| } | ||||
| 
 | ||||
| DEFAULT_EXCLUDES=(/.git/ /.toinst.conf) | ||||
| DEFAULT_RSYNC_OPTIONS=(-rptL --delete) | ||||
| 
 | ||||
| VARS=( | ||||
|     TOMCAT_PROFILE | ||||
|     CATALINA_BASE TOMCAT_USER TOMCAT_GROUP TOMCAT_VERSION | ||||
|     MANAGER_URL MANAGER_USER MANAGER_PASSWORD | ||||
|     BACKUP RESTART | ||||
| ) | ||||
| ARRAYS=( | ||||
|     WAMAPS | ||||
|     EXCLUDES REPLACE_EXCLUDES | ||||
|     PROTECTS | ||||
|     RSYNC_OPTIONS REPLACE_RSYNC_OPTIONS | ||||
| ) | ||||
| function __reset_vars() { | ||||
|     local var | ||||
|     for var in "${VARS[@]}"; do | ||||
|         eval "$var=" | ||||
|     done | ||||
|     for var in "${ARRAYS[@]}"; do | ||||
|         eval "$var=()" | ||||
|     done | ||||
| } | ||||
| function __dump_vars() { | ||||
|     local var | ||||
|     for var in "${VARS[@]}"; do | ||||
|         eecho "$(echo_setv2 "$var")" | ||||
|     done | ||||
|     for var in "${ARRAYS[@]}"; do | ||||
|         eecho "$(echo_seta2 "$var")" | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function use_manager_script() { | ||||
|     local v="$TOMCAT_VERSION" | ||||
|     if [ -z "$v" ]; then | ||||
|         return 0 | ||||
|     elif [[ "$v" == 6.0.* ]]; then | ||||
|         if [ "${v#6.0.}" -ge 30 ]; then | ||||
|             return 0 | ||||
|         else | ||||
|             return 1 | ||||
|         fi | ||||
|     elif [ "${v%%.*}" -gt 6 ]; then | ||||
|         return 0 | ||||
|     else | ||||
|         return 1 | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| function parse_server() { | ||||
|     local -a lines | ||||
|     local serverxml port | ||||
|     serverxml="$CATALINA_BASE/conf/server.xml" | ||||
|     array_from_lines lines "$(xpathtool -g "/Server/Service[@name='Catalina']/Connector/@port" "$serverxml")" | ||||
|     port="${lines[0]}" | ||||
|     if [ -n "$port" ]; then | ||||
|         if use_manager_script; then | ||||
|             MANAGER_URL="http://localhost:$port/manager/text" | ||||
|         else | ||||
|             MANAGER_URL="http://localhost:$port/manager/html" | ||||
|         fi | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| function parse_tomcat_users() { | ||||
|     local -a lines | ||||
|     local usersxml role | ||||
|     usersxml="$CATALINA_BASE/conf/tomcat-users.xml" | ||||
|     if use_manager_script; then | ||||
|         role=manager-script | ||||
|     else | ||||
|         role=manager-gui | ||||
|     fi | ||||
|     array_from_lines lines "$(xpathtool -g "/tomcat-users/user[contains(@roles,'$role')]/@username" "$usersxml")" | ||||
|     MANAGER_USER="${lines[0]}" | ||||
|     if [ -n "$MANAGER_USER" ]; then | ||||
|         array_from_lines lines "$(xpathtool -g "/tomcat-users/user[@username='$MANAGER_USER']/@password" "$usersxml")" | ||||
|         MANAGER_PASSWORD="${lines[0]}" | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| function build_rsync_options() { | ||||
|     local -a excludes protects; local exclude protect | ||||
|     if [ ${#REPLACE_EXCLUDES[*]} -gt 0 ]; then | ||||
|         array_copy excludes REPLACE_EXCLUDES | ||||
|     else | ||||
|         array_copy excludes DEFAULT_EXCLUDES | ||||
|     fi | ||||
|     array_extend excludes EXCLUDES | ||||
|     array_copy protects PROTECTS | ||||
|     if [ ${#REPLACE_RSYNC_OPTIONS[*]} -gt 0 ]; then | ||||
|         array_copy rsync_options REPLACE_RSYNC_OPTIONS | ||||
|     else | ||||
|         array_copy rsync_options DEFAULT_RSYNC_OPTIONS | ||||
|     fi | ||||
|     array_extend rsync_options RSYNC_OPTIONS | ||||
| 
 | ||||
|     local toinstconf="$1/.toinst.conf" | ||||
|     if [ -f "$toinstconf" ]; then | ||||
|         eval "$( | ||||
|             EXCLUDES=() | ||||
|             PROTECTS=() | ||||
|             RSYNC_OPTIONS=() | ||||
|             source "$toinstconf" | ||||
|             array_extend excludes EXCLUDES | ||||
|             array_extend protects PROTECTS | ||||
|             array_extend rsync_options RSYNC_OPTIONS | ||||
|             echo_seta2 excludes | ||||
|             echo_seta2 protects | ||||
|             echo_seta2 rsync_options | ||||
|         )" | ||||
|     fi | ||||
|     for exclude in "${excludes[@]}"; do | ||||
|         array_add rsync_options --exclude "$exclude" | ||||
|     done | ||||
|     for protect in "${PROTECTS[@]}"; do | ||||
|         array_add rsync_options  -f "P $protect" | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| args=(% | ||||
|     --help '$exit_with display_help' | ||||
|     --config-template action=config-template | ||||
|     --private-parse-server '$action=parse; parse_server=1' | ||||
|     --private-parse-tomcat-users '$action=parse; parse_tomcat_users=1' | ||||
|     --is-tmpdir '$istmpdir=1; tmpdir=.' | ||||
|     -c:,--config: config= | ||||
|     -C:,--config-profile: tomcat_profile= | ||||
|     -d:,--catalina-base:,--catalina-home: catalina_base= | ||||
|     -U:,--tomcat-user: tomcat_user= | ||||
|     -G:,--tomcat-group: tomcat_group= | ||||
|     -V:,--tomcat-version: tomcat_version= | ||||
|     -g:,--manager-url: manager_url= | ||||
|     -u:,--user: manager_user= | ||||
|     -p:,--password: manager_password= | ||||
|     -m:,--wamap: wamaps | ||||
|     --exclude: excludes | ||||
|     --replace-excludes: replace_excludes | ||||
|     --protect: protects | ||||
|     --rsync-option: rsync_options | ||||
|     --replace-rsync-options: replace_rsync_options | ||||
|     -b,--backup backup=1 | ||||
|     --no-backup backup=0 | ||||
|     -B,--backup-only action=backup | ||||
|     --restart restart=1 | ||||
|     -n,--no-restart restart=0 | ||||
|     -r,--restart-only action=restart | ||||
|     --fake fake=1 | ||||
| ) | ||||
| parse_args "$@"; set -- "${args[@]}" | ||||
| 
 | ||||
| [ -n "$action" ] || action=deploy | ||||
| 
 | ||||
| if [ "$action" == parse ]; then | ||||
|     CATALINA_BASE="$1" | ||||
|     TOMCAT_VERSION="$2" | ||||
|     if [ -n "$parse_server" ]; then | ||||
|         parse_server | ||||
|         echo_setv2 MANAGER_URL | ||||
|     fi | ||||
|     if [ -n "$parse_tomcat_users" ]; then | ||||
|         parse_tomcat_users | ||||
|         echo_setv2 MANAGER_USER | ||||
|         echo_setv2 MANAGER_PASSWORD | ||||
|     fi | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| # Charger la configuration | ||||
| __reset_vars | ||||
| if [ -n "$config" ]; then | ||||
|     eval "$( | ||||
|         __reset_vars | ||||
|         CATALINA_HOME= | ||||
|         source "$config" 2>/dev/null || exit 1 | ||||
|         [ -n "$CATALINA_BASE" ] || CATALINA_BASE="$CATALINA_HOME" | ||||
|         __dump_vars | ||||
|     )" | ||||
| fi | ||||
| 
 | ||||
| # Traiter la ligne de commande | ||||
| for var in "${VARS[@]}"; do | ||||
|     lvar="${var,,}" | ||||
|     if [ -n "${!lvar}" ]; then | ||||
|         setv "$var" "${!lvar}" | ||||
|     fi | ||||
| done | ||||
| [ -n "$RESTART" ] || RESTART=1 # valeur par défaut | ||||
| normyesvals BACKUP RESTART | ||||
| for var in "${ARRAYS[@]}"; do | ||||
|     lvar="${var,,}" | ||||
|     if ! array_isempty "$lvar"; then | ||||
|         array_copy "$var" "$lvar" | ||||
|     fi | ||||
| done | ||||
| array_fix_paths WAMAPS , | ||||
| 
 | ||||
| # Calculer le profil de connexion | ||||
| if [ -z "$TOMCAT_PROFILE" ]; then | ||||
|     for v in 8 7; do | ||||
|         if [ -d /var/lib/tomcat$v ]; then | ||||
|             TOMCAT_PROFILE=debian:tomcat$v | ||||
|             break | ||||
|         fi | ||||
|     done | ||||
| fi | ||||
| if [ -z "$TOMCAT_PROFILE" ]; then | ||||
|     v= | ||||
|     if [ -L /opt/tomcat ]; then | ||||
|         setx v=readlink /opt/tomcat | ||||
|         setx v=basename -- "$v" | ||||
|     else | ||||
|         array_lsdirs ts /opt "apache-tomcat-*" | ||||
|         if [ ${#ts[*]} -gt 0 ]; then | ||||
|             [ -n "$CATALINA_BASE" ] || CATALINA_BASE="${ts[0]}" | ||||
|             v="$CATALINA_BASE" | ||||
|             [ -L "$v" ] && setx v=readlink "$v" | ||||
|             setx v=basename -- "$v" | ||||
|         fi | ||||
|     fi | ||||
|     if [ -n "$v" ] && [[ "$v" == apache-tomcat-* ]]; then | ||||
|         v=${v#apache-tomcat-} | ||||
|         mv=${v%%.*} | ||||
|         if [ -f /etc/init.d/tomcat$mv ]; then | ||||
|             TOMCAT_PROFILE=runs:tomcat$mv | ||||
|         else | ||||
|             TOMCAT_PROFILE=runs:tomcat | ||||
|         fi | ||||
|         [ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v" | ||||
|     fi | ||||
| fi | ||||
| if [ -n "$TOMCAT_PROFILE" ]; then | ||||
|     case "$TOMCAT_PROFILE" in | ||||
|     debian:*|runs:*) ;; | ||||
|     d:*) TOMCAT_PROFILE="debian:tomcat${TOMCAT_PROFILE#d:}";; | ||||
|     *) TOMCAT_PROFILE="runs:$TOMCAT_PROFILE";; | ||||
|     esac | ||||
| fi | ||||
| 
 | ||||
| # Calculer les valeurs dérivées du profil de connexion | ||||
| case "$TOMCAT_PROFILE" in | ||||
| debian:*) | ||||
|     t="${TOMCAT_PROFILE#debian:}" | ||||
|     v="${t#tomcat}" | ||||
|     [ -z "$CATALINA_BASE" ] && CATALINA_BASE="/var/lib/$t" | ||||
|     eval "$( | ||||
|         setv "${t^^}_USER" | ||||
|         setv "${t^^}_GROUP" | ||||
|         source "/etc/default/$t" 2>/dev/null | ||||
|         eval "echo tomcat_user=\"\$${t^^}_USER\"" | ||||
|         eval "echo tomcat_group=\"\$${t^^}_GROUP\"" | ||||
|     )" | ||||
|     [ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user" | ||||
|     [ -z "$TOMCAT_GROUP" ] && TOMCAT_GROUP="$tomcat_group" | ||||
|     [ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v" | ||||
|     ;; | ||||
| runs:*) | ||||
|     v="${TOMCAT_PROFILE#runs:tomcat}" | ||||
|     if [ -z "$CATALINA_BASE" -a "$v" != "$TOMCAT_PROFILE" ]; then | ||||
|         array_lsdirs ts /opt "apache-tomcat-$v*" | ||||
|         CATALINA_BASE="${ts[0]}" | ||||
|     fi | ||||
|     if [ -z "$CATALINA_BASE" ]; then | ||||
|         if [ -L /opt/tomcat ]; then | ||||
|             setx CATALINA_BASE=readlink /opt/tomcat | ||||
|         else | ||||
|             array_lsdirs ts /opt "apache-tomcat-*" | ||||
|             CATALINA_BASE="${ts[0]}" | ||||
|         fi | ||||
|     fi | ||||
|     name="${TOMCAT_PROFILE#runs:}" | ||||
|     eval "$( | ||||
|         TOMCAT_USER= | ||||
|         source "/etc/default/$name" 2>/dev/null | ||||
|         echo tomcat_user="$TOMCAT_USER" | ||||
|     )" | ||||
|     [ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user" | ||||
|     if [ -z "$TOMCAT_VERSION" ]; then | ||||
|         v="$CATALINA_BASE" | ||||
|         [ -L "$v" ] && setx v=readlink "$v" | ||||
|         setx v=basename -- "$v" | ||||
|         if [[ "$v" == apache-tomcat-* ]]; then | ||||
|             TOMCAT_VERSION="${v#apache-tomcat-}" | ||||
|         fi | ||||
|     fi | ||||
|     ;; | ||||
| esac | ||||
| 
 | ||||
| # Calculer les valeurs dérivées des fichiers de $CATALINA_BASE | ||||
| 
 | ||||
| if [ -n "$CATALINA_BASE" -a -n "$TOMCAT_VERSION" ]; then | ||||
|     if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then | ||||
|         # lire les fichiers de configuratione et déterminer MANAGER_URL, | ||||
|         # MANAGER_USER et MANAGER_PASSWORD | ||||
|         if is_root; then | ||||
|             [ -z "$MANAGER_URL" ] && parse_server | ||||
|             [ -z "$MANAGER_USER" ] && parse_tomcat_users | ||||
|         else | ||||
|             args=() | ||||
|             [ -z "$MANAGER_URL" ] && array_add args --private-parse-server | ||||
|             [ -z "$MANAGER_USER" ] && array_add args --private-parse-tomcat-users | ||||
|             array_add args "$CATALINA_BASE" "$TOMCAT_VERSION" | ||||
|             eval "$(run_as root --noexec "${args[@]}")" | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| # A partir de la liste des webapps et de WAMAPS, construire une liste de couples | ||||
| # waname:src pour la sauvegarde et/ou le déploiement | ||||
| 
 | ||||
| [ -n "$fake" -o "$action" == config-template ] && will_deploy= || will_deploy=1 | ||||
| 
 | ||||
| if [ $# -eq 0 -a -n "$will_deploy" ]; then | ||||
|     [ -d WEB-INF ] && src=. || src= | ||||
|     read_value "Veuillez entrer la webapp à déployer" src "$src" O | ||||
|     set -- "$src" | ||||
| elif [ $# -eq 0 -a "$action" == config-template ]; then | ||||
|     [ -d WEB-INF ] && set . | ||||
| fi | ||||
| 
 | ||||
| srcs=() | ||||
| [ -n "$istmpdir" ] || ac_set_tmpdir tmpdir | ||||
| for src in "$@"; do | ||||
|     if [ -f "$src" ] && is_archive "$src"; then | ||||
|         setx waname=get_archive_appname "$src" | ||||
|         wadir="$tmpdir/$waname" | ||||
|         mkdir "$wadir" | ||||
|         if extract_archive "$src" "$wadir"; then | ||||
|             array_add srcs "$wadir" | ||||
|         else | ||||
|             eerror "$src: erreur lors de l'extraction de l'archive" | ||||
|         fi | ||||
|     elif [ -d "$src" ]; then | ||||
|         array_add srcs "$(abspath "$src")" | ||||
|     elif [ -e "$src" ]; then | ||||
|         eerror "$src: fichier invalide" | ||||
|     else | ||||
|         eerror "$src: fichier ou répertoire introuvable" | ||||
|     fi | ||||
| done | ||||
| [ ${#srcs[*]} -gt 0 -o -z "$will_deploy" ] || die | ||||
| 
 | ||||
| deploymaps=() | ||||
| for src in "${srcs[@]}"; do | ||||
|     setx waname=basename -- "$src" | ||||
|     found= | ||||
|     for wamap in "${WAMAPS[@]}"; do | ||||
|         splitpair "$wamap" from to | ||||
|         if [ "$waname" == "$from" ]; then | ||||
|             found=1 | ||||
|             array_add deploymaps "$to:$src" | ||||
|         fi | ||||
|     done | ||||
|     if [ -z "$found" ]; then | ||||
|         array_add deploymaps "$waname:$src" | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Maintenant, nous pouvons faire les actions | ||||
| 
 | ||||
| if [ "$action" == config-template ]; then | ||||
|     if [ ${#deploymaps[*]} -gt 0 ]; then | ||||
|         toinstconfname=.toinst.conf | ||||
|     else | ||||
|         toinstconfname=toinst.conf | ||||
|         deploymaps=(:.) | ||||
|     fi | ||||
|     for deploymap in "${deploymaps[@]}"; do | ||||
|         splitpair "$deploymap" waname src | ||||
|         toinstconf="$src/$toinstconfname" | ||||
|         if [ -f "$toinstconf" ]; then | ||||
|             estepi "$(ppath "$toinstconf"): configuration déjà existante" | ||||
|         else | ||||
|             estep "$(ppath "$toinstconf")" | ||||
|             echo >"$toinstconf" "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| 
 | ||||
| # Fichiers à exclure de la source lors du déploiement | ||||
| #EXCLUDES=() | ||||
| 
 | ||||
| # Fichiers à protéger dans la destination lors du déploiement | ||||
| #PROTECTS=() | ||||
| 
 | ||||
| # Options supplémentaires de rsync à utiliser pour le déploiement | ||||
| #RSYNC_OPTIONS=()" | ||||
|         fi | ||||
|     done | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| ## Sauvegarde | ||||
| if [ -n "$BACKUP" -o "$action" == backup ]; then | ||||
|     [ -n "$CATALINA_BASE" -o -z "$will_deploy" ] || die "Vous devez spécifier l'option --catalina-base" | ||||
| 
 | ||||
|     home_bckdir="$HOME/tomcat-backups" | ||||
|     if [ -n "$istmpdir" ]; then | ||||
|         # déploiement distant: sauvegarder dans le répertoire utilisateur | ||||
|         default_bckdir="$home_bckdir" | ||||
|     else | ||||
|         # déploiement local: ça dépend de la webapp | ||||
|         default_bckdir= | ||||
|     fi | ||||
|     setx cwd=pwd | ||||
| 
 | ||||
|     etitle "Sauvegarde des webapps" | ||||
|     for deploymap in "${deploymaps[@]}"; do | ||||
|         splitpair "$deploymap" waname src | ||||
|         wadir="$CATALINA_BASE/webapps/$waname" | ||||
| 
 | ||||
|         if [ ! -d "$wadir" ]; then | ||||
|             einfo "$waname: la webapp n'a pas encore été déployée. elle ne sera pas sauvegardée" | ||||
|             continue | ||||
|         fi | ||||
| 
 | ||||
|         bckdir="$default_bckdir" | ||||
|         if [ -z "$bckdir" ]; then | ||||
|             if withinpath "$tmpdir" "$src"; then | ||||
|                 bckdir="$home_bckdir" | ||||
|             elif withinpath "$src" "$cwd"; then | ||||
|                 setx bckdir=dirname "$src" | ||||
|             else | ||||
|                 bckdir=. | ||||
|             fi | ||||
|         fi | ||||
|         mkdir -p "$bckdir" | ||||
| 
 | ||||
|         setx base=date +%y%m%d | ||||
|         i=0 | ||||
|         bckname="$base.$profile$i-$waname" | ||||
|         while [ -d "$bckdir/$bckname" ]; do | ||||
|             let i=$i+1 | ||||
|             bckname="$base.$profile$i-$waname" | ||||
|         done | ||||
| 
 | ||||
|         if [ -n "$fake" ]; then | ||||
|             evalx qvals rsync -a "$wadir/" "$bckdir/$bckname" // eecho | ||||
|         else | ||||
|             estep "$wadir --> $(ppath "$bckdir/$bckname")" | ||||
|             if ! rsync -a "$wadir/" "$bckdir/$bckname"; then | ||||
|                 ewarn "Une erreur s'est produite pendant la sauvegarde" | ||||
|                 ask_yesno "Voulez-vous continuer le déploiement?" N || die | ||||
|             fi | ||||
|         fi | ||||
|     done | ||||
|     eend | ||||
| fi | ||||
| 
 | ||||
| ## Déploiement | ||||
| if [ "$action" == deploy ]; then | ||||
|     [ -n "$CATALINA_BASE" -o -z "$will_deploy" ] || die "Vous devez spécifier l'option --catalina-base" | ||||
| 
 | ||||
|     if [ -n "$fake" ]; then | ||||
|         # Afficher ce qu'il faut faire | ||||
|         etitle "Configuration globale" __dump_vars | ||||
|         etitle "Déploiements des webapps" | ||||
|         for deploymap in "${deploymaps[@]}"; do | ||||
|             splitpair "$deploymap" waname src | ||||
|             setx srcname=basename -- "$src" | ||||
|             dest="${CATALINA_BASE:-CATALINA_BASE}/webapps/$waname" | ||||
|             etitle "$waname" | ||||
|             if [ -f "$src/.toinst.conf" ]; then | ||||
|                 etitle "Configuration de la webapp" | ||||
|                 ( | ||||
|                     EXCLUDES=() | ||||
|                     PROTECTS=() | ||||
|                     RSYNC_OPTIONS=() | ||||
|                     source "$src/.toinst.conf" | ||||
|                     for var in EXCLUDES PROTECTS RSYNC_OPTIONS; do | ||||
|                         eecho "$(echo_seta2 "$var")" | ||||
|                     done | ||||
|                 ) | ||||
|                 eend | ||||
|             fi | ||||
|             build_rsync_options "$src" | ||||
|             evalx qvals rsync "${rsync_options[@]}" "$src/" "$dest" // eecho | ||||
|             evalx qvals chmod -R u=rwX,g=rX,o=rX "$dest" // eecho | ||||
|             if [ -n "$TOMCAT_USER" ]; then | ||||
|                 evalx qvals chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" // eecho | ||||
|             fi | ||||
|             eend | ||||
|         done | ||||
|         eend | ||||
| 
 | ||||
|     elif ! is_root; then | ||||
|         # le déploiement doit être fait en root | ||||
|         args=( | ||||
|             -C "$TOMCAT_PROFILE" | ||||
|             -d "$CATALINA_BASE" | ||||
|             -U "$TOMCAT_USER" | ||||
|             -G "$TOMCAT_GROUP" | ||||
|             -V "$TOMCAT_VERSION" | ||||
|             -g "$MANAGER_URL" | ||||
|             -u "$MANAGER_USER" | ||||
|             -p "$MANAGER_PASSWORD" | ||||
|             -m "$(array_join WAMAPS ,)" | ||||
|             --no-backup | ||||
|             --no-restart | ||||
|         ) | ||||
|         run_as root --noexec "${args[@]}" "${srcs[@]}" || die | ||||
| 
 | ||||
|     else | ||||
|         # faire le déploiement | ||||
|         etitle "Déploiements des webapps" | ||||
|         for deploymap in "${deploymaps[@]}"; do | ||||
|             splitpair "$deploymap" waname src | ||||
|             setx srcname=basename -- "$src" | ||||
|             dest="$CATALINA_BASE/webapps/$waname" | ||||
|             etitle "$srcname" | ||||
|             estepi "Déploiement vers $dest" | ||||
|             estep "Copie des fichiers" | ||||
|             build_rsync_options "$src" | ||||
|             if ! rsync "${rsync_options[@]}" "$src/" "$dest"; then | ||||
|                 eerror "Une erreur s'est produite pendant la copie des fichiers" | ||||
|             else | ||||
|                 error= | ||||
|                 estep "Correction des permissions et du propriétaire" | ||||
|                 chmod -R u=rwX,g=rX,o=rX "$dest" || error=1 | ||||
|                 if [ -n "$TOMCAT_USER" ]; then | ||||
|                     chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" || error=1 | ||||
|                 fi | ||||
|                 if [ -n "$error" ]; then | ||||
|                     eeror "Une erreur s'est produite pendant la mise à jour" | ||||
|                 fi | ||||
|             fi | ||||
|             eend | ||||
|         done | ||||
|         eend | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| ## Redémarrage | ||||
| if [ -n "$RESTART" -o "$action" == restart ]; then | ||||
|     etitle "Redémarrage des webapps" | ||||
|     if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then | ||||
|         ewarn "Impossible de recharger la webapp parce que l'url du manager et/ou le compte admin n'ont pas pu être déterminés." | ||||
|         [ -z "$fake" ] && enote "\ | ||||
| Par défaut, les webapps ne sont rechargées automatiquement que si le fichier web.xml est modifié. | ||||
| Utilisez les options -g, -u, -p pour spécifier les informations manquantes nécessaires au pilotage du manager." | ||||
| 
 | ||||
|     elif [ -n "$fake" ]; then | ||||
|         estepi "Utilisation du manager à l'adresse $MANAGER_URL" | ||||
|         for deploymap in "${deploymaps[@]}"; do | ||||
|             splitpair "$deploymap" waname src | ||||
|             etitle "$waname" | ||||
|             evalx qvals curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" // eecho | ||||
|             eend | ||||
|         done | ||||
| 
 | ||||
|     else | ||||
|         estepi "Utilisation du manager à l'adresse $MANAGER_URL" | ||||
|         for deploymap in "${deploymaps[@]}"; do | ||||
|             splitpair "$deploymap" waname src | ||||
|             ebegin "$waname" | ||||
|             curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" >/dev/null | ||||
|             eend $? | ||||
|         done | ||||
|     fi | ||||
|     eend | ||||
| fi | ||||
							
								
								
									
										276
									
								
								ufile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										276
									
								
								ufile
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,276 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS | ||||
| 
 | ||||
| function display_help() { | ||||
|     uecho "$scriptname: classer des fichiers selon certains règles | ||||
| 
 | ||||
| Les règles sont spécifiées dans le fichier ~/etc/default/ufile | ||||
| 
 | ||||
| Dans ce fichier, le tableau RULES contient des règles qui sont chacune de la | ||||
| forme pattern:destdir[:renamef] | ||||
| 
 | ||||
| - pattern est au format glob et identifie les fichiers auxquels s'applique la | ||||
|   règle | ||||
| - destdir est le répertoire de destination dans lequel classer le fichier | ||||
| - renamef est une fonction qui permet de supporter le renommage d'un fichier | ||||
|   lors de son classement. Sa signature est 'renamef filename pf destdir' où | ||||
|   filename est le nom du fichier source, pf son chemin complet et destdir la | ||||
|   valeur de destdir mentionnée dans la règle. | ||||
|   La fonction doit définir la variable dest qui est le nouveau nom. Si la | ||||
|   fonction retourne un code d'erreur autre que zéro, la règle est ignorée. | ||||
|   Si le nouveau nom contient un chemin, destdir est ignoré et le fichier est | ||||
|   déplacé dans le répertoire spécifié avec le nom spécifié. Si dest est un | ||||
|   tableau avec plusieurs destinations, alors le fichier est copié en plusieurs | ||||
|   fois. | ||||
|   Si dest est de la forme [user@]host:path alors le fichier est copié par scp | ||||
|   sur l'hôte spécifié vers la destination spécifiée, sauf si l'hôte courant est | ||||
|   déjà celui mentionné dans la valeur, auquel cas la copie est faite directement | ||||
|   dans le répertoire spécifié. | ||||
|   Si le user et l'hôte courant sont déjà à la valeur spécifiée, alors la copie | ||||
|   est faite en local sans utiliser scp sauf si l'option --force-scp est utilisée | ||||
|   Le chemin spécifié, en local ou distant, est toujours le chemin complet vers | ||||
|   le fichier destination. Si on veut copier le fichier sans le renommer vers un | ||||
|   répertoire, il faut mettre un slash e.g destdir/ ou user@host:destdir/ | ||||
|   variables pouvant être définies mais non documentées: interaction(=-i) | ||||
| 
 | ||||
| USAGE | ||||
|     $scriptname [options] <files...> | ||||
| 
 | ||||
| OPTIONS | ||||
|     -c, --config CONFIG | ||||
|         Utiliser le fichier de configuration spécifié au lieu de la valeur par | ||||
|         défaut ~/etc/default/ufile | ||||
|     --file | ||||
|         Classer les fichiers spécifiés. C'est l'action par défaut | ||||
|     -S, --ssh SSH | ||||
|         S'il faut classer sur un hôte distant avec scp, utiliser le programme | ||||
|         spécifié pour la connexion par ssh | ||||
|     --force-scp | ||||
|         Toujours utiliser scp pour une copie distante. Par défaut s'il est | ||||
|         déterminé que l'hôte distant est en réalité l'hôte courant, alors la | ||||
|         copie est effectuée directement. | ||||
|     -n, --fake | ||||
|         Afficher les opérations qui seraient faites | ||||
|     -l, --list | ||||
|         Lister les règles définies | ||||
|     -e, --edit | ||||
|         Lancer un éditeur sur le fichier de configuration" | ||||
| } | ||||
| 
 | ||||
| function joinp() { | ||||
|     # afficher le chemin $1/$2 | ||||
|     local pf="$1" | ||||
|     [ -n "$2" -a "${pf%/}" == "$pf" ] && pf="$pf/" | ||||
|     pf="$pf${2#/}" | ||||
|     echo "$pf" | ||||
| } | ||||
| 
 | ||||
| function __check_destdir() { | ||||
|     local destdir="$1" rule="$2" | ||||
|     if [ -z "$destdir" ]; then | ||||
|         eerror "$rule: règle invalide: destdir est vide" | ||||
|         return 1 | ||||
|     fi | ||||
|     return 0 | ||||
| } | ||||
| function __set_dest() { | ||||
|     local dest="$1" destdir="$2" filename="$3" force_scp="$4" | ||||
|     local userhost remotedir destname | ||||
|     if [[ "$dest" == *:* ]]; then | ||||
|         splitpair "$dest" userhost remotedir | ||||
|         if [ -z "$force_scp" ] && check_userhostname "$userhost"; then | ||||
|             # on est déjà avec le bon user sur le bon hôte | ||||
|             if [ -n "$remotedir" ]; then | ||||
|                 splitpath "$remotedir" destdir destname | ||||
|                 setx destdir=abspath "$destdir" "$HOME" | ||||
|                 [ -n "$destname" ] || destname="$filename" | ||||
|                 setx dest=joinp "$destdir" "$destname" | ||||
|             else | ||||
|                 setx dest=joinp "$HOME" "$filename" | ||||
|             fi | ||||
|         fi | ||||
|     elif [[ "$dest" == */* ]]; then | ||||
|         splitpath "$dest" destdir destname | ||||
|         [ -n "$destname" ] || destname="$filename" | ||||
|         setx dest=joinp "$destdir" "$destname" | ||||
|         setx dest=abspath "$dest" | ||||
|     else | ||||
|         __check_destdir "$destdir" "$rule" || return 1 | ||||
|         setx dest=joinp "$destdir" "$filename" | ||||
|     fi | ||||
|     upvar dest "$dest" | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| args=(% | ||||
|     --help '$exit_with display_help' | ||||
|     -c:,--config: config= | ||||
|     --file action=file | ||||
|     -S:,--ssh: SSH= | ||||
|     --force-scp force_scp=1 | ||||
|     -n,--fake fake=1 | ||||
|     -l,--list action=list | ||||
|     -e,--edit action=edit | ||||
| ) | ||||
| parse_args "$@"; set -- "${args[@]}" | ||||
| 
 | ||||
| [ -n "$action" ] || action=file | ||||
| 
 | ||||
| ## charger toutes les règles | ||||
| 
 | ||||
| RULES=() | ||||
| INCLUDES=() | ||||
| if [ -n "$config" ]; then | ||||
|     if [ "$action" != edit ]; then | ||||
|         # le fichier doit exister, sauf en mode édition où il sera créé s'il | ||||
|         # n'existe pas déjà | ||||
|         [ -f "$config" ] || die "$config: fichier introuvable" | ||||
|     fi | ||||
|     if [ -f "$config" ]; then | ||||
|         source "$config" || die "$config: erreur lors de la lecture du fichier" | ||||
|     fi | ||||
| else | ||||
|     set_defaults ufile | ||||
| fi | ||||
| array_copy rules RULES | ||||
| for include in "${INCLUDES[@]}"; do | ||||
|     if [ -f "$include" ]; then | ||||
|         RULES=() | ||||
|         source "$include" | ||||
|         array_extend rules RULES | ||||
|     else | ||||
|         ewarn "$include: fichier introuvable" | ||||
|     fi | ||||
| done | ||||
| array_copy RULES rules | ||||
| 
 | ||||
| ## actions particulières | ||||
| 
 | ||||
| if [ "$action" == list ]; then | ||||
|     echo "# $(echo_seta2 INCLUDES)" | ||||
|     array_to_lines RULES | ||||
|     exit 0 | ||||
| elif [ "$action" == edit ]; then | ||||
|     [ -n "$config" ] || setx config=get_user_defaults_file ufile | ||||
|     if [ ! -f "$config" ]; then | ||||
|         einfo "Le fichier $(ppath "$config") n'existe pas. Il sera créé avec un contenu par défaut" | ||||
|         mkdirof "$config" || die | ||||
|         cp "$scriptdir/lib/default/ufile" "$config" | ||||
|     fi | ||||
|     "${EDITOR:-vi}" "$config" | ||||
|     exit $? | ||||
| elif [ "$action" != file ]; then | ||||
|     die "bug: $action: action non implémentée" | ||||
| fi | ||||
| 
 | ||||
| ## classement des fichiers | ||||
| 
 | ||||
| if [ -n "$fake" ]; then | ||||
|     function docmd() { qvals "$@"; } | ||||
| else | ||||
|     function docmd() { "$@"; } | ||||
| fi | ||||
| 
 | ||||
| [ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer" | ||||
| [ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile" | ||||
| 
 | ||||
| # vérifier les règles | ||||
| for rule in "${RULES[@]}"; do | ||||
|     splitpair "$rule" pattern r2 | ||||
|     splitpair "$r2" destdir r3 | ||||
|     splitpair "$r3" renamef r4 | ||||
|     if [ -z "$destdir" -o "${destdir#"~/"}" != "$destdir" ]; then | ||||
|         : | ||||
|     elif [ "${destdir#/}" == "$destdir" ]; then | ||||
|         ewarn "$rule: règle potentiellement problématique: destdir devrait être absolu" | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| # faire le classement effectif | ||||
| r= | ||||
| for file in "$@"; do | ||||
|     [ -f "$file" -o -n "$fake" ] || { | ||||
|         eerror "$file: fichier introuvable. il sera ignoré" | ||||
|         continue | ||||
|     } | ||||
|     setx pf=abspath "$file" | ||||
|     setx dir=dirname -- "$pf" | ||||
|     setx filename=basename -- "$pf" | ||||
|     found= | ||||
|     for rule in "${RULES[@]}"; do | ||||
|         splitpair "$rule" pattern r2 | ||||
|         splitpair "$r2" odestdir r3 | ||||
|         splitpair "$r3" renamef r4 | ||||
|         if [ "${odestdir#"~/"}" != "$odestdir" ]; then | ||||
|             odestdir="$HOME/${odestdir#"~/"}" | ||||
|         elif [ "$odestdir" == "~" ]; then | ||||
|             odestdir="$HOME" | ||||
|         fi | ||||
| 
 | ||||
|         eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue | ||||
| 
 | ||||
|         unset dest | ||||
|         interaction=--DEFAULT-- | ||||
|         if [ -n "$renamef" ]; then | ||||
|             "$renamef" "$filename" "$pf" "$odestdir" || continue | ||||
|         fi | ||||
|         if is_array dest; then | ||||
|             array_copy tmpdests dest | ||||
|             dests=() | ||||
|             for dest in "${tmpdests[@]}"; do | ||||
|                 __set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break | ||||
|                 array_add dests "$dest" | ||||
|             done | ||||
|         elif is_defined dest; then | ||||
|             __set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break | ||||
|             dests=("$dest") | ||||
|         else | ||||
|             __check_destdir "$odestdir" "$rule" || break | ||||
|             setx dest=joinp "$odestdir" "$filename" | ||||
|             dests=("$dest") | ||||
|         fi | ||||
| 
 | ||||
|         i=1 | ||||
|         mvi=${#dests[*]} | ||||
|         for dest in "${dests[@]}"; do | ||||
|             if [[ "$dest" == *:* ]]; then | ||||
|                 [ "$interaction" == --DEFAULT-- ] && int= || int="$interaction" | ||||
|                 estep "$filename --> $dest" | ||||
|                 ask_yesno $int "Voulez-vous continuer?" O || { | ||||
|                     r=1; found=x; break | ||||
|                 } | ||||
|                 docmd scp ${SSH:+-S "$SSH"} "$file" "$dest" || die "problème lors de la copie du fichier" | ||||
| 
 | ||||
|             else | ||||
|                 [ "$interaction" == --DEFAULT-- ] && int=-i || int="$interaction" | ||||
|                 estep "$filename --> $dest" | ||||
|                 ask_yesno $int "Voulez-vous continuer?" O || { | ||||
|                     r=1; found=x; break | ||||
|                 } | ||||
|                 setx destdir=dirname -- "$dest" | ||||
|                 docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire" | ||||
|                 if [ $i -eq $mvi ]; then | ||||
|                     mvdesc="du déplacement" | ||||
|                     mvcmd=mv | ||||
|                 else | ||||
|                     mvdesc="de la copie" | ||||
|                     mvcmd=cp | ||||
|                 fi | ||||
|                 docmd "$mvcmd" -i "$file" "$dest" || die "problème lors $mvdesc du fichier" | ||||
|             fi | ||||
|             i=$(($i + 1)) | ||||
|         done | ||||
| 
 | ||||
|         [ -n "$found" ] || found=1 | ||||
|         break | ||||
|     done | ||||
| 
 | ||||
|     if [ -z "$found" ]; then | ||||
|         ewarn "$file: aucune correspondance n'a été trouvée" | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| [ -n "$r" ] || r=0 | ||||
| exit $r | ||||
							
								
								
									
										2
									
								
								uinst
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								uinst
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| source "$(dirname -- "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS uinst | ||||
| 
 | ||||
| uinst_nolocal "$@" | ||||
|  | ||||
							
								
								
									
										2
									
								
								uinst.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								uinst.sh
									
									
									
									
									
								
							| @ -2,7 +2,7 @@ | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| # Version de uinst qui fonctionne avec /bin/sh. Le contrôle est transmis à | ||||
| # bash, qui est recherché dans une liste de répertoires standards | ||||
| . `dirname "$0"`/lib/ulib/ulibsh || exit 1 | ||||
| . `dirname -- "$0"`/lib/ulib/ulibsh || exit 1 | ||||
| urequire DEFAULTS uinst | ||||
| 
 | ||||
| uinst_nolocal "$@" | ||||
|  | ||||
							
								
								
									
										162
									
								
								uproject
									
									
									
									
									
								
							
							
						
						
									
										162
									
								
								uproject
									
									
									
									
									
								
							| @ -61,10 +61,27 @@ COMMANDS | ||||
|         Cloner un dépôt distant. Basculer sur la branche develop si elle existe. | ||||
|         Initialiser git annex si le dépôt contient des fichiers annexés. | ||||
|         Récupérer aussi ces fichiers avec 'git annex get' | ||||
|         -n, --no-clone | ||||
|             Ne pas cloner, afficher simplement ce qui serait fait | ||||
|         -u, --update | ||||
|             Si le dépôt a déjà été cloné, le mettre à jour avec git pull | ||||
|         -m, --master | ||||
|             Ne pas chercher à basculer sur la branche develop, même si elle | ||||
|             existe. | ||||
|         -r, --recursive | ||||
|             Cloner récursivement tous les dépôt à partir du chemin spécifié | ||||
|             depuis un serveur gitolite. La signature est alors sensiblement | ||||
|             différente: | ||||
|                 clone -r git@host:basepath [destdir] | ||||
|                 clone -r http://host/gituser/basepath [destdir] | ||||
|             L'arborescence en dessous de basepath est recréée à partir de | ||||
|             destdir, e.g le dépôt git@host:basepath/to/repo est cloné dans | ||||
|             destdir/to/repo | ||||
| 
 | ||||
|     crone git@host:path/to/repo [destdir] | ||||
|     crone http://host/gituser/path/to/repo [destdir] | ||||
|         Créer un dépôt distant sur gitolite, puis le cloner | ||||
|         Créer un dépôt sur un serveur gitolite, puis le cloner. La commande | ||||
|         'create' doit avoir été activée sur ce serveur. | ||||
| 
 | ||||
|     develop | ||||
|     release | ||||
| @ -268,26 +285,131 @@ elif array_contains GITANNEX_CMDS "$CMD"; then | ||||
|     esac | ||||
| 
 | ||||
| elif [ "$CMD" == clone ]; then | ||||
|     repourl="${1%.git}" | ||||
|     [ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt git" | ||||
|     splitfsep "$repourl" : userhost path | ||||
| 
 | ||||
|     destdir="$2" | ||||
|     if [ -z "$destdir" ]; then | ||||
|         setx destdir=basename -- "$path" | ||||
|         destdir="${destdir%.git}" | ||||
|     fi | ||||
|     [ -d "$destdir" ] && die "$(ppath "$destdir"): répertoire existant" | ||||
| 
 | ||||
|     git_annex_use_ssh_wrapper | ||||
|     git clone "$repourl" "$destdir" || die | ||||
|     ( | ||||
|         cd "$destdir" | ||||
|         if git_have_rbranch develop; then | ||||
|             git checkout develop || exit 1 | ||||
|     function 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 | ||||
|     ) || die | ||||
|     git_annex_initial "$destdir" || die | ||||
|         git_annex_initial "$2" || return 1 | ||||
|     } | ||||
|     function 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 filter_repos() { | ||||
|         awkrun 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 | ||||
| } | ||||
| ' | ||||
|     } | ||||
| 
 | ||||
|     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[@]}" || die "$args" | ||||
| 
 | ||||
|     if [ -n "$recursive" ]; then | ||||
|         repobase="$1" | ||||
|         [ -n "$repobase" ] || die "Vous devez spécifier l'url de base des dépôts à cloner" | ||||
|         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" ] || die "Vous devez spécifier l'hôte e.g http://host/git/basepath" | ||||
|             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" ] || die "Vous devez spécifier l'hôte" | ||||
|             urlbase="$user@$host" | ||||
|         fi | ||||
|         basepath="${basepath%/}" | ||||
|         destbase="${2:-.}" | ||||
| 
 | ||||
|         git_annex_use_ssh_wrapper | ||||
|         prefix="${basepath:+$basepath/}" | ||||
|         array_from_lines repos "$(set -o pipefail; gitolite_info "$mode" "$urlbase" "$prefix" | filter_repos "$prefix")" || die | ||||
|         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 | ||||
|                     ) || die | ||||
|                 else | ||||
|                     estepe "$(ppath2 "$destdir"): répertoire existant" | ||||
|                 fi | ||||
|             elif [ -n "$no_clone" ]; then | ||||
|                 qvals git clone "$repourl" "$destdir" | ||||
|             else | ||||
|                 pclone "$repourl" "$destdir" "$nodevelop" || die | ||||
|             fi | ||||
|         done | ||||
| 
 | ||||
|     else | ||||
|         repourl="${1%.git}" | ||||
|         [ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt git" | ||||
| 
 | ||||
|         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 | ||||
|                 ) || die | ||||
|             else | ||||
|                 estepe "$(ppath2 "$destdir"): répertoire existant" | ||||
|             fi | ||||
|         elif [ -n "$no_clone" ]; then | ||||
|             qvals git clone "$repourl" "$destdir" | ||||
|         else | ||||
|             pclone "$repourl" "$destdir" "$nodevelop" || die | ||||
|         fi | ||||
|     fi | ||||
| 
 | ||||
| elif [ "$CMD" == crone ]; then | ||||
|     repourl="${1%.git}" | ||||
| @ -318,7 +440,7 @@ elif [ "$CMD" == crone ]; then | ||||
|     fi | ||||
|     tmpdestdir= | ||||
|     if [ -d "$destdir" ]; then | ||||
|         [ -d "$destdir/.git" ] && die "$(ppath "$destdir"): répertoire existant" | ||||
|         [ -d "$destdir/.git" ] && die "$(ppath2 "$destdir"): un dépôt existe déjà" | ||||
|         ac_set_tmpdir tmpdestdir | ||||
|     fi | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										2
									
								
								woinst
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								woinst
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| source "$(dirname -- "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS woinst | ||||
| 
 | ||||
| woinst "$@" | ||||
|  | ||||
							
								
								
									
										8
									
								
								woinst.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								woinst.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #!/bin/sh | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| # Version de woinst qui fonctionne avec /bin/sh. Le contrôle est transmis à | ||||
| # bash, qui est recherché dans une liste de répertoires standards | ||||
| . `dirname -- "$0"`/lib/ulib/ulibsh || exit 1 | ||||
| urequire DEFAULTS woinst | ||||
| 
 | ||||
| woinst "$@" | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user