<pman>Intégration de la branche rel82-0.4.0

This commit is contained in:
Jephté Clain 2025-03-14 15:24:39 +04:00
commit fd120298a9
46 changed files with 1030 additions and 1128 deletions

8
.pman.yml Normal file
View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
composer:
profiles: [ dev, dist ]
dev:
link: true
dist:
link: false

View File

@ -1,3 +1,33 @@
## Release 0.4.0p82 du 14/03/2025-15:24
## Release 0.4.0p74 du 14/03/2025-15:23
* `cf9fab5` maj src/php
* `5c5d878` pdev: option --force-merge
* `9723c14` ajout cl::same_keys()
* `5ae3e8b` pdev: ajout --after-merge
* `cfc386d` Revert "prel/pdev: tracer les hooks"
* `d44537a` prel/pdev: tracer les hooks
* `e8abaca` supprimer tests qui sont encore dans nur/ture
* `a3116e5` ajout du schéma
* `0d2ca20` prel/pdev: option --fake
* `bd0da9c` prel/pdev: ajouter les hook BEFORE_*
* `7e05caf` runphp: passer les arguments inchangés à composer
* `9def939` p: support des projets dépendants composer
* `01c65a6` tests verbosity et interaction
* `8e3569a` ne plus utiliser tooenc par défaut. renommer tooenc en uecho
* `ead5b5a` support automatique options verbosity et interaction
* `8825493` pman: tenir compte des branches distantes
* `e129e0a` ajout pwip
* `9a2378b` pman: améliorer l'ergonomie
* `8cfd803` gestion des profils composer
* `d9989c6` supprimer composer.phar puisque c'est fourni par runphp
* `7eb5efb` ajout config .pman.yml
* `92363cd` pman: option --force-create
* `3b379eb` maj doc
* `bbb5559` pman: ajout init pman
* `939f772` pman: support des config standard nommées
## Release 0.3.4p82 du 01/03/2025-06:23 ## Release 0.3.4p82 du 01/03/2025-06:23
## Release 0.3.4p74 du 01/03/2025-06:22 ## Release 0.3.4p74 du 01/03/2025-06:22

View File

@ -1 +1 @@
0.3.4 0.4.0

View File

@ -6,15 +6,15 @@ function __esection() {
local length="${COLUMNS:-80}" local length="${COLUMNS:-80}"
setx lsep=__complete "$prefix" "$length" - setx lsep=__complete "$prefix" "$length" -
tooenc "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" recho "$COULEUR_BLEUE$lsep$COULEUR_NORMALE"
[ -n "$*" ] || return 0 [ -n "$*" ] || return 0
length=$((length - 1)) length=$((length - 1))
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
setx line=__complete "$prefix- $line" "$length" setx line=__complete "$prefix- $line" "$length"
tooenc "$COULEUR_BLEUE$line-$COULEUR_NORMALE" recho "$COULEUR_BLEUE$line-$COULEUR_NORMALE"
done done
tooenc "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" recho "$COULEUR_BLEUE$lsep$COULEUR_NORMALE"
} }
function __etitle() { function __etitle() {
local -a lines; local maxlen=0 local -a lines; local maxlen=0
@ -23,10 +23,10 @@ function __etitle() {
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
[ ${#line} -gt $maxlen ] && maxlen=${#line} [ ${#line} -gt $maxlen ] && maxlen=${#line}
tooenc "${prefix}${COULEUR_BLEUE}T $line$COULEUR_NORMALE" recho "${prefix}${COULEUR_BLEUE}T $line$COULEUR_NORMALE"
done done
maxlen=$((maxlen + 2)) maxlen=$((maxlen + 2))
tooenc "${prefix}${COULEUR_BLEUE}T$(__complete "" $maxlen -)${COULEUR_NORMALE}" recho "${prefix}${COULEUR_BLEUE}T$(__complete "" $maxlen -)${COULEUR_NORMALE}"
} }
function __edesc() { function __edesc() {
local -a lines local -a lines
@ -34,7 +34,7 @@ function __edesc() {
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
tooenc "${prefix}${COULEUR_BLEUE}>${COULEUR_NORMALE} $line" recho "${prefix}${COULEUR_BLEUE}>${COULEUR_NORMALE} $line"
done done
} }
function __ebanner() { function __ebanner() {
@ -43,35 +43,35 @@ function __ebanner() {
local length="${COLUMNS:-80}" local length="${COLUMNS:-80}"
setx lsep=__complete "$prefix" "$length" = setx lsep=__complete "$prefix" "$length" =
tooenc "$COULEUR_ROUGE$lsep" recho "$COULEUR_ROUGE$lsep"
length=$((length - 1)) length=$((length - 1))
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "" "${lines[@]}" ""; do for line in "" "${lines[@]}" ""; do
setx line=__complete "$prefix= $line" "$length" setx line=__complete "$prefix= $line" "$length"
tooenc "$line=" recho "$line="
done done
tooenc "$lsep$COULEUR_NORMALE" recho "$lsep$COULEUR_NORMALE"
} }
function __eimportant() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}!${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __eimportant() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}!${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __eattention() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}*${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __eattention() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}*${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __eerror() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}E${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __eerror() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}E${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __ewarn() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}W${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __ewarn() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}W${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __enote() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}N${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __enote() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}N${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __einfo() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLEUE}I${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __einfo() { recho "$(__edate)$(__eindent0)${COULEUR_BLEUE}I${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __edebug() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLANCHE}D${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __edebug() { recho "$(__edate)$(__eindent0)${COULEUR_BLANCHE}D${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estep() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estep() { recho "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepe() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepe() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepw() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepw() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepn() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepn() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepi() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepi() { recho "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estep_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estep_() { recho_ "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepe_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepe_() { recho_ "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepw_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepw_() { recho_ "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepn_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepn_() { recho_ "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __estepi_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __estepi_() { recho_ "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __action() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __action() { recho "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __asuccess() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __asuccess() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __afailure() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}${COULEUR_NORMALE} $(__eindent "$1" " ")"; } function __afailure() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}${COULEUR_NORMALE} $(__eindent "$1" " ")"; }
function __adone() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } function __adone() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; }

View File

@ -6,23 +6,23 @@ function __esection() {
local length="${COLUMNS:-80}" local length="${COLUMNS:-80}"
setx lsep=__complete "$prefix" "$length" - setx lsep=__complete "$prefix" "$length" -
tooenc "$lsep" recho "$lsep"
[ -n "$*" ] || return 0 [ -n "$*" ] || return 0
length=$((length - 1)) length=$((length - 1))
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
setx line=__complete "$prefix- $line" "$length" setx line=__complete "$prefix- $line" "$length"
tooenc "$line-" recho "$line-"
done done
tooenc "$lsep" recho "$lsep"
} }
function __etitle() { function __etitle() {
local p="TITLE: " i=" " local p="TITLE: " i=" "
tooenc "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" recho "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")"
} }
function __edesc() { function __edesc() {
local p="DESC: " i=" " local p="DESC: " i=" "
tooenc "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" recho "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")"
} }
function __ebanner() { function __ebanner() {
local -a lines local -a lines
@ -30,37 +30,37 @@ function __ebanner() {
local length="${COLUMNS:-80}" local length="${COLUMNS:-80}"
setx lsep=__complete "$prefix" "$length" = setx lsep=__complete "$prefix" "$length" =
tooenc "$lsep" recho "$lsep"
length=$((length - 1)) length=$((length - 1))
setx -a lines=echo "$1" setx -a lines=echo "$1"
for line in "" "${lines[@]}" ""; do for line in "" "${lines[@]}" ""; do
setx line=__complete "$prefix= $line" "$length" setx line=__complete "$prefix= $line" "$length"
tooenc "$line=" recho "$line="
done done
tooenc "$lsep" recho "$lsep"
} }
function __eimportant() { tooenc "$(__edate)$(__eindent0)IMPORTANT! $(__eindent "$1" " ")"; } function __eimportant() { recho "$(__edate)$(__eindent0)IMPORTANT! $(__eindent "$1" " ")"; }
function __eattention() { tooenc "$(__edate)$(__eindent0)ATTENTION! $(__eindent "$1" " ")"; } function __eattention() { recho "$(__edate)$(__eindent0)ATTENTION! $(__eindent "$1" " ")"; }
function __eerror() { tooenc "$(__edate)$(__eindent0)ERROR: $(__eindent "$1" " ")"; } function __eerror() { recho "$(__edate)$(__eindent0)ERROR: $(__eindent "$1" " ")"; }
function __ewarn() { tooenc "$(__edate)$(__eindent0)WARNING: $(__eindent "$1" " ")"; } function __ewarn() { recho "$(__edate)$(__eindent0)WARNING: $(__eindent "$1" " ")"; }
function __enote() { tooenc "$(__edate)$(__eindent0)NOTE: $(__eindent "$1" " ")"; } function __enote() { recho "$(__edate)$(__eindent0)NOTE: $(__eindent "$1" " ")"; }
function __einfo() { tooenc "$(__edate)$(__eindent0)INFO: $(__eindent "$1" " ")"; } function __einfo() { recho "$(__edate)$(__eindent0)INFO: $(__eindent "$1" " ")"; }
function __edebug() { tooenc "$(__edate)$(__eindent0)DEBUG: $(__eindent "$1" " ")"; } function __edebug() { recho "$(__edate)$(__eindent0)DEBUG: $(__eindent "$1" " ")"; }
function __eecho() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } function __eecho() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; }
function __eecho_() { tooenc_ "$(__edate)$(__eindent0)$(__eindent "$1")"; } function __eecho_() { recho_ "$(__edate)$(__eindent0)$(__eindent "$1")"; }
function __estep() { tooenc "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } function __estep() { recho "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; }
function __estepe() { tooenc "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } function __estepe() { recho "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; }
function __estepw() { tooenc "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } function __estepw() { recho "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; }
function __estepn() { tooenc "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } function __estepn() { recho "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; }
function __estepi() { tooenc "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } function __estepi() { recho "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; }
function __estep_() { tooenc_ "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } function __estep_() { recho_ "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; }
function __estepe_() { tooenc_ "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } function __estepe_() { recho_ "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; }
function __estepw_() { tooenc_ "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } function __estepw_() { recho_ "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; }
function __estepn_() { tooenc_ "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } function __estepn_() { recho_ "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; }
function __estepi_() { tooenc_ "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } function __estepi_() { recho_ "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; }
function __action() { tooenc "$(__edate)$(__eindent0)ACTION: $(__eindent "$1" " ")"; } function __action() { recho "$(__edate)$(__eindent0)ACTION: $(__eindent "$1" " ")"; }
function __asuccess() { tooenc "$(__edate)$(__eindent0)(OK) $(__eindent "$1" " ")"; } function __asuccess() { recho "$(__edate)$(__eindent0)(OK) $(__eindent "$1" " ")"; }
function __afailure() { tooenc "$(__edate)$(__eindent0)(KO) $(__eindent "$1" " ")"; } function __afailure() { recho "$(__edate)$(__eindent0)(KO) $(__eindent "$1" " ")"; }
function __adone() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } function __adone() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; }

View File

@ -124,8 +124,8 @@ optdesc
commence par ++, c'est une option avancée qui n'est pas affichée par défaut." commence par ++, c'est une option avancée qui n'est pas affichée par défaut."
function parse_args() { function parse_args() {
eval "$NULIB__DISABLE_SET_X" eval "$NULIB__DISABLE_SET_X"
[ -n "$NULIB_ARGS_ONERROR_RETURN" ] && set_die_return
local __r= local __r=
local __DIE='[ -n "$NULIB_ARGS_ONERROR_RETURN" ] && return 1 || die'
if ! is_array args; then if ! is_array args; then
eerror "Invalid args definition: args must be defined" eerror "Invalid args definition: args must be defined"
@ -145,17 +145,33 @@ function parse_args() {
__r=1 __r=1
else else
__DEFS=("$@") __DEFS=("$@")
__parse_args || __r=1 __nulib_args_parse_args || __r=1
fi fi
eval "$NULIB__ENABLE_SET_X" eval "$NULIB__ENABLE_SET_X"
if [ -n "$__r" ]; then if [ -n "$__r" ]; then
eval "$__DIE" die || return
fi fi
} }
function __parse_args() { function __nulib_args_add_sopt() {
local noauto="$1"; shift
local def
for def in "$@"; do
array_contains "$noauto" "$def" || __sopts="$__sopts$def"
done
}
function __nulib_args_add_lopt() {
local noauto="$1"; shift
local def
for def in "$@"; do
array_contains "$noauto" "$def" || __lopts="$__lopts${__lopts:+,}$def"
done
}
function __nulib_args_parse_args() {
## tout d'abord, construire la liste des options ## tout d'abord, construire la liste des options
local __AUTOH=1 __AUTOHELP=1 # faut-il gérer automatiquement l'affichage de l'aide? local __AUTOH=1 __AUTOHELP=1 # faut-il gérer automatiquement l'affichage de l'aide?
local __AUTOD=1 __AUTODEBUG=1 # faut-il rajouter les options -D et --debug local -a __NOAUTOL __NOAUTOLOGTO # faut-il rajouter les options pour gérer la journalisation?
local -a __NOAUTOV __NOAUTOVERBOSITY # options de verbosité qui ont été définies par l'utilisateur
local -a __NOAUTOI __NOAUTOINTERACTION # options d'interaction qui ont été définies par l'utilisateur
local __ADVHELP # y a-t-il des options avancées? local __ADVHELP # y a-t-il des options avancées?
local __popt __sopts __lopts local __popt __sopts __lopts
local -a __defs local -a __defs
@ -165,10 +181,10 @@ function __parse_args() {
+) __popt="$1"; shift; continue;; +) __popt="$1"; shift; continue;;
-) __popt="$1"; shift; continue;; -) __popt="$1"; shift; continue;;
-*) IFS=, read -a __defs <<<"$1"; shift;; -*) IFS=, read -a __defs <<<"$1"; shift;;
*) eerror "Invalid arg definition: expected option, got '$1'"; eval "$__DIE";; *) die "Invalid arg definition: expected option, got '$1'" || return;;
esac esac
# est-ce que l'option prend un argument? # est-ce que l'option prend un argument?
local __def __witharg __valdesc local __def __longdef __witharg __valdesc
__witharg= __witharg=
for __def in "${__defs[@]}"; do for __def in "${__defs[@]}"; do
if [ "${__def%::*}" != "$__def" ]; then if [ "${__def%::*}" != "$__def" ]; then
@ -180,23 +196,36 @@ function __parse_args() {
# définitions __sopts et __lopts # définitions __sopts et __lopts
for __def in "${__defs[@]}"; do for __def in "${__defs[@]}"; do
__def="${__def%%:*}" __def="${__def%%:*}"
__longdef=
if [[ "$__def" == --* ]]; then if [[ "$__def" == --* ]]; then
# --longopt # --longopt
__def="${__def#--}" __def="${__def#--}"
__lopts="$__lopts${__lopts:+,}$__def$__witharg" __lopts="$__lopts${__lopts:+,}$__def$__witharg"
__longdef=1
elif [[ "$__def" == -* ]] && [ ${#__def} -eq 2 ]; then elif [[ "$__def" == -* ]] && [ ${#__def} -eq 2 ]; then
# -o # -o
__def="${__def#-}" __def="${__def#-}"
__sopts="$__sopts$__def$__witharg" __sopts="$__sopts$__def$__witharg"
[ "$__def" == h ] && __AUTOH= case "$__def" in
[ "$__def" == D ] && __AUTOD= h) __AUTOH=;;
L) __NOAUTOL+=("-$__def");;
Q|q|v|D) __NOAUTOV+=("-$__def");;
b|y|i) __NOAUTOI+=("-$__def");;
esac
else else
# -longopt ou longopt # -longopt ou longopt
__def="${__def#-}" __def="${__def#-}"
__lopts="$__lopts${__lopts:+,}$__def$__witharg" __lopts="$__lopts${__lopts:+,}$__def$__witharg"
__longdef=1
fi
if [ -n "$__longdef" ]; then
case "$__def" in
help|help++) __AUTOHELP=;;
log-to) __NOAUTOLOGTO+=("--$__def");;
very-quiet|quiet|verbose|debug) __NOAUTOVERBOSITY+=("--$__def");;
batch|automatic|interactive) __NOAUTOINTERACTION+=("--$__def");;
esac
fi fi
[ "$__def" == help -o "$__def" == help++ ] && __AUTOHELP=
[ "$__def" == debug ] && __AUTODEBUG=
done done
# sauter l'action # sauter l'action
shift shift
@ -209,8 +238,12 @@ function __parse_args() {
[ -n "$__AUTOH" ] && __sopts="${__sopts}h" [ -n "$__AUTOH" ] && __sopts="${__sopts}h"
[ -n "$__AUTOHELP" ] && __lopts="$__lopts${__lopts:+,}help,help++" [ -n "$__AUTOHELP" ] && __lopts="$__lopts${__lopts:+,}help,help++"
[ -n "$__AUTOD" ] && __sopts="${__sopts}D" __nulib_args_add_sopt __NOAUTOL L
[ -n "$__AUTODEBUG" ] && __lopts="$__lopts${__lopts:+,}debug" __nulib_args_add_lopt __NOAUTOLOGTO log-to
__nulib_args_add_sopt __NOAUTOV Q q v D
__nulib_args_add_lopt __NOAUTOVERBOSITY very-quiet quiet verbose debug
__nulib_args_add_sopt __NOAUTOI b y i
__nulib_args_add_lopt __NOAUTOINTERACTION batch automatic interactive
__sopts="$__popt$__sopts" __sopts="$__popt$__sopts"
local -a __getopt_args local -a __getopt_args
@ -222,7 +255,7 @@ function __parse_args() {
else else
# relancer pour avoir le message d'erreur # relancer pour avoir le message d'erreur
LANG=C getopt "${__getopt_args[@]}" 2>&1 1>/dev/null LANG=C getopt "${__getopt_args[@]}" 2>&1 1>/dev/null
eval "$__DIE" die || return
fi fi
## puis traiter les options ## puis traiter les options
@ -373,7 +406,7 @@ $prefix$usage"
fi fi
[[ "$1" == -* ]] || break [[ "$1" == -* ]] || break
option_="$1"; shift option_="$1"; shift
__parse_opt "$option_" __nulib_args_parse_opt "$option_"
if [ -n "$__witharg" ]; then if [ -n "$__witharg" ]; then
# l'option prend un argument # l'option prend un argument
value_="$1"; shift value_="$1"; shift
@ -387,7 +420,7 @@ $prefix$usage"
unset -f inc@ res@ add@ set@ showhelp@ unset -f inc@ res@ add@ set@ showhelp@
args=("$@") args=("$@")
} }
function __parse_opt() { function __nulib_args_parse_opt() {
# $1 est l'option spécifiée # $1 est l'option spécifiée
local option_="$1" local option_="$1"
set -- "${__DEFS[@]}" set -- "${__DEFS[@]}"
@ -460,27 +493,62 @@ function __parse_opt() {
[ -n "$__found" ] && return 0 [ -n "$__found" ] && return 0
done done
if [ -n "$__AUTOH" -a "$option_" == -h ]; then case "$option_" in
__action="showhelp@" -h)
if [ -n "$__AUTOH" ]; then
__action='showhelp@'
return 0 return 0
fi fi
;;
--help)
if [ -n "$__AUTOHELP" ]; then if [ -n "$__AUTOHELP" ]; then
if [ "$option_" == --help ]; then __action='showhelp@'
__action="showhelp@"
return 0
elif [ "$option_" == --help++ ]; then
__action="showhelp@ ++"
return 0 return 0
fi fi
fi ;;
if [ -n "$__AUTOD" -a "$option_" == -D ]; then --help++)
__action=set_debug if [ -n "$__AUTOHELP" ]; then
__action='showhelp@ ++'
return 0 return 0
fi fi
if [ -n "$__AUTODEBUG" -a "$option_" == --debug ]; then ;;
__action=set_debug -L)
if ! array_contains __NOAUTOL "$option_"; then
__action='elogto $value_'
return 0 return 0
fi fi
;;
--log-to)
if ! array_contains __NOAUTOL "$option_"; then
__action='elogto $value_'
return 0
fi
;;
-Q|-q|-v|-D)
if ! array_contains __NOAUTOV "$option_"; then
__action='set_verbosity $option_'
return 0
fi
;;
--very-quiet|--quiet|--verbose|--debug)
if ! array_contains __NOAUTOVERBOSITY "$option_"; then
__action='set_verbosity $option_'
return 0
fi
;;
-b|-y|-i)
if ! array_contains __NOAUTOI "$option_"; then
__action='set_interaction $option_'
return 0
fi
;;
--batch|--automatic|--interactive)
if ! array_contains __NOAUTOINTERACTION "$option_"; then
__action='set_interaction $option_'
return 0
fi
;;
esac
# ici, l'option n'a pas été trouvée, on ne devrait pas arriver ici # ici, l'option n'a pas été trouvée, on ne devrait pas arriver ici
eerror "Unexpected option '$option_'"; eval "$__DIE" die "Unexpected option '$option_'" || return
} }

View File

@ -62,7 +62,7 @@ function ask_yesno() {
else else
__eecho_ "Voulez-vous continuer?" 1>&2 __eecho_ "Voulez-vous continuer?" 1>&2
fi fi
tooenc_ " $prompt " 1>&2 echo_ " $prompt " 1>&2
uread r uread r
is_yes "${r:-$default}" is_yes "${r:-$default}"
else else
@ -198,17 +198,17 @@ function __rv_read() {
__eecho_ "Entrez la valeur" 1>&2 __eecho_ "Entrez la valeur" 1>&2
fi fi
if [ -n "$__rv_readline" ]; then if [ -n "$__rv_readline" ]; then
tooenc_ ": " 1>&2 echo_ ": " 1>&2
uread -e ${__rv_d:+-i"$__rv_d"} "${__rv_opts[@]}" __rv_r uread -e ${__rv_d:+-i"$__rv_d"} "${__rv_opts[@]}" __rv_r
else else
if [ -n "$__rv_d" ]; then if [ -n "$__rv_d" ]; then
if [ -n "$__rv_showdef" ]; then if [ -n "$__rv_showdef" ]; then
tooenc_ " [$__rv_d]" 1>&2 echo_ " [$__rv_d]" 1>&2
else else
tooenc_ " [****]" 1>&2 echo_ " [****]" 1>&2
fi fi
fi fi
tooenc_ ": " 1>&2 echo_ ": " 1>&2
uread "${__rv_opts[@]}" __rv_r uread "${__rv_opts[@]}" __rv_r
[ -n "$__rv_nl" ] && echo [ -n "$__rv_nl" ] && echo
fi fi
@ -217,6 +217,7 @@ function __rv_read() {
_setv "$__rv_v" "$__rv_r" _setv "$__rv_v" "$__rv_r"
return 0 return 0
fi fi
echo
done done
} }
@ -268,7 +269,7 @@ function simple_menu() {
else else
__eecho_ "Entrez le numéro de l'option choisie" 1>&2 __eecho_ "Entrez le numéro de l'option choisie" 1>&2
fi fi
tooenc_ ": " 1>&2 echo_ ": " 1>&2
uread __sm_choice uread __sm_choice
# Valeur par défaut # Valeur par défaut
@ -291,7 +292,7 @@ function simple_menu() {
let __sm_c=$__sm_c+1 let __sm_c=$__sm_c+1
if [ "$__sm_c" -eq 5 ]; then if [ "$__sm_c" -eq 5 ]; then
# sauter une ligne toutes les 4 tentatives # sauter une ligne toutes les 4 tentatives
tooenc "" 1>&2 echo 1>&2
__sm_c=0 __sm_c=0
fi fi
done done
@ -438,7 +439,7 @@ function __void_actions_menu() {
if [ $c -eq 0 ]; then if [ $c -eq 0 ]; then
[ -n "$title" ] && __etitle "$title" 1>&2 [ -n "$title" ] && __etitle "$title" 1>&2
__eecho_ "=== Actions disponibles: " 1>&2 __eecho_ "=== Actions disponibles: " 1>&2
tooenc "$action_title" 1>&2 recho "$action_title" 1>&2
fi fi
if [ -n "$actyc" ]; then if [ -n "$actyc" ]; then
__eecho_ "$actyc" 1>&2 __eecho_ "$actyc" 1>&2
@ -447,7 +448,7 @@ function __void_actions_menu() {
else else
__eecho_ "Entrez l'action à effectuer" 1>&2 __eecho_ "Entrez l'action à effectuer" 1>&2
fi fi
tooenc_ ": " 1>&2 echo_ ": " 1>&2
uread choice uread choice
if [ -z "$choice" -a -n "$default_action" ]; then if [ -z "$choice" -a -n "$default_action" ]; then
select_action="$default_action" select_action="$default_action"
@ -468,7 +469,7 @@ function __void_actions_menu() {
let c=$c+1 let c=$c+1
if [ $c -eq 5 ]; then if [ $c -eq 5 ]; then
# sauter une ligne toutes les 4 tentatives # sauter une ligne toutes les 4 tentatives
tooenc "" 1>&2 echo 1>&2
c=0 c=0
fi fi
done done
@ -484,21 +485,21 @@ function __options_actions_menu() {
i=1 i=1
for option in "${options[@]}"; do for option in "${options[@]}"; do
if [ "$option" == "$select_option" ]; then if [ "$option" == "$select_option" ]; then
tooenc "$i*- $option" 1>&2 echo "$i*- $option" 1>&2
else else
tooenc "$i - $option" 1>&2 echo "$i - $option" 1>&2
fi fi
let i=$i+1 let i=$i+1
done done
__estepn_ "Actions disponibles: " 1>&2 __estepn_ "Actions disponibles: " 1>&2
tooenc "$action_title" 1>&2 recho "$action_title" 1>&2
fi fi
if [ -n "$optyc" ]; then if [ -n "$optyc" ]; then
__eecho_ "$optyc" 1>&2 __eecho_ "$optyc" 1>&2
else else
__eecho_ "Entrez l'action et le numéro de l'option choisie" 1>&2 __eecho_ "Entrez l'action et le numéro de l'option choisie" 1>&2
fi fi
tooenc_ ": " 1>&2 echo_ ": " 1>&2
uread choice uread choice
# vérifier la saisie # vérifier la saisie
@ -572,7 +573,7 @@ function __options_actions_menu() {
let c=$c+1 let c=$c+1
if [ $c -eq 5 ]; then if [ $c -eq 5 ]; then
# sauter une ligne toutes les 4 tentatives # sauter une ligne toutes les 4 tentatives
tooenc "" 1>&2 echo "" 1>&2
c=0 c=0
fi fi
done done

View File

@ -83,7 +83,7 @@ function err_isatty() {
################################################################################ ################################################################################
function tooenc() { function uecho() {
# $1 étant une chaine encodée en utf-8, l'afficher dans l'encoding de sortie $2 # $1 étant une chaine encodée en utf-8, l'afficher dans l'encoding de sortie $2
# qui vaut par défaut $NULIB_OUTPUT_ENCODING # qui vaut par défaut $NULIB_OUTPUT_ENCODING
local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}" local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}"
@ -93,9 +93,8 @@ function tooenc() {
iconv -f -utf-8 -t "$to" <<<"$value" iconv -f -utf-8 -t "$to" <<<"$value"
fi fi
} }
function uecho() { tooenc "$*"; }
function tooenc_() { function uecho_() {
# $1 étant une chaine encodée en utf-8, l'afficher sans passer à la ligne dans # $1 étant une chaine encodée en utf-8, l'afficher sans passer à la ligne dans
# l'encoding de sortie $2 qui vaut par défaut $NULIB_OUTPUT_ENCODING # l'encoding de sortie $2 qui vaut par défaut $NULIB_OUTPUT_ENCODING
local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}" local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}"
@ -105,7 +104,6 @@ function tooenc_() {
recho_ "$value" | iconv -f utf-8 -t "$to" recho_ "$value" | iconv -f utf-8 -t "$to"
fi fi
} }
function uecho_() { tooenc_ "$*"; }
export NULIB_QUIETLOG export NULIB_QUIETLOG
export NULIB__TMPLOG export NULIB__TMPLOG
@ -210,7 +208,7 @@ function __eindent() {
# indenter les lignes de $1, sauf la première # indenter les lignes de $1, sauf la première
local -a lines; local line first=1 local -a lines; local line first=1
local indent="$(__eindent0)$2" local indent="$(__eindent0)$2"
setx -a lines=echo "$1" setx -a lines=recho "$1"
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
if [ -n "$first" ]; then if [ -n "$first" ]; then
recho "$line" recho "$line"
@ -232,7 +230,11 @@ function __complete() {
} }
PRETTYOPTS=() PRETTYOPTS=()
function set_verbosity() { :;} function set_verbosity() {
case "$1" in
-D|--debug) NULIB_DEBUG=1;;
esac
}
function check_verbosity() { return 0; } function check_verbosity() { return 0; }
function get_verbosity_option() { :;} function get_verbosity_option() { :;}

View File

@ -2,20 +2,13 @@
## configuration par défaut ## configuration par défaut
# branche upstream
UPSTREAM= UPSTREAM=
# branches de développement
DEVELOP=develop DEVELOP=develop
FEATURE=wip/ FEATURE=wip/
# branche de préparation de release
RELEASE=release- RELEASE=release-
# branche de release
MAIN=master MAIN=master
TAG_PREFIX= TAG_PREFIX=
TAG_SUFFIX= TAG_SUFFIX=
# branche de hotfix
HOTFIX=hotfix- HOTFIX=hotfix-
# branche de distribution
DIST= DIST=
# désactiver les releases automatiques?
NOAUTO= NOAUTO=

View File

@ -5,15 +5,23 @@
# les branches sont mergées dans cet ordre: # les branches sont mergées dans cet ordre:
# upstream --> develop --> [release -->] main --> dist # upstream --> develop --> [release -->] main --> dist
# feature _/ hotfix _/ # feature _/ hotfix _/
# branche upstream
UPSTREAM= UPSTREAM=
# branches de développement
DEVELOP=develop DEVELOP=develop
FEATURE=wip/ FEATURE=wip/
# branche de préparation de release
RELEASE=release- RELEASE=release-
# branche de release
MAIN=master MAIN=master
TAG_PREFIX= TAG_PREFIX=
TAG_SUFFIX= TAG_SUFFIX=
# branche de hotfix
HOTFIX=hotfix- HOTFIX=hotfix-
# branche de distribution
DIST= DIST=
# désactiver les releases automatiques?
NOAUTO= NOAUTO=
CONFIG_VARS=( CONFIG_VARS=(
@ -151,6 +159,7 @@ function load_branches() {
local what="${1:-all}"; shift local what="${1:-all}"; shift
case "$what" in case "$what" in
all) all)
[ -n "$Origin" ] || Origin=origin
setx CurrentBranch=git_get_branch setx CurrentBranch=git_get_branch
setx -a LocalBranches=git_list_branches setx -a LocalBranches=git_list_branches
setx -a RemoteBranches=git_list_rbranches "$Origin" setx -a RemoteBranches=git_list_rbranches "$Origin"
@ -187,12 +196,12 @@ function load_branches() {
ReleaseBranch= ReleaseBranch=
HotfixBranch= HotfixBranch=
MainBranch= MainBranch=
Dist=Branch DistBranch=
for branch in "${AllBranches[@]}"; do for branch in "${LocalBranches[@]}"; do
if [ "$branch" == "$UPSTREAM" ]; then if [ "$branch" == "$UPSTREAM" ]; then
UpstreamBranch="$branch" UpstreamBranch="$branch"
elif [[ "$branch" == "$FEATURE"* ]]; then elif [[ "$branch" == "$FEATURE"* ]]; then
FeatureBranch+=("$branch") FeatureBranches+=("$branch")
elif [ "$branch" == "$DEVELOP" ]; then elif [ "$branch" == "$DEVELOP" ]; then
DevelopBranch="$branch" DevelopBranch="$branch"
elif [[ "$branch" == "$RELEASE"* ]]; then elif [[ "$branch" == "$RELEASE"* ]]; then
@ -210,31 +219,50 @@ function load_branches() {
} }
function load_config() { function load_config() {
if [ "${ConfigFile#::}" != "$ConfigFile" ]; then
ConfigFile="$NULIBDIR/bash/src/pman${ConfigFile#::}.conf.sh"
fi
if [ -n "$ConfigFile" ]; then if [ -n "$ConfigFile" ]; then
source "$ConfigFile" || die || return source "$ConfigFile" || die || return
elif [ -n "$ConfigBranch" ]; then elif [ -n "$ConfigBranch" ]; then
# c'est le seul cas où ConfigFile reste vide
if ! array_contains LocalBranches "$ConfigBranch"; then if ! array_contains LocalBranches "$ConfigBranch"; then
die "$ConfigBranch: branche de configuration introuvable" || return die "$ConfigBranch: branche de configuration introuvable" || return
else else
ac_set_tmpfile ConfigFile local config
git show "$ConfigBranch:.pman.conf" >"$ConfigFile" 2>/dev/null ac_set_tmpfile config
[ -s "$ConfigFile" ] || die "$ConfigBranch: aucune configuration trouvée sur cette branche" || return git show "$ConfigBranch:.pman.conf" >"$config" 2>/dev/null
source "$ConfigFile" [ -s "$config" ] || die "$ConfigBranch: aucune configuration trouvée sur cette branche" || return
source "$config"
fi fi
elif [ -f .pman.conf ]; then elif [ -f .pman.conf ]; then
ConfigFile="$(pwd)/.pman.conf" ConfigFile="$(pwd)/.pman.conf"
source "$ConfigFile" source "$ConfigFile"
elif [ -n "${MYNAME#prel}" ]; then elif [ -n "$1" -a -n "${MYNAME#$1}" ]; then
ConfigFile="$NULIBDIR/bash/src/pman${MYNAME#$1}.conf.sh" ConfigFile="$NULIBDIR/bash/src/pman${MYNAME#$1}.conf.sh"
source "$ConfigFile" source "$ConfigFile"
else else
ConfigFile="$NULIBDIR/bash/src/pman.conf.sh" ConfigFile="$NULIBDIR/bash/src/pman.conf.sh"
fi fi
# S'assurer que nulib est dans le PATH pour que les scripts utilisateurs
# puissent utiliser les outils fournis
export PATH="$NULIBDIR/bin:$PATH"
} }
################################################################################ ################################################################################
# Divers # Divers
function resolve_should_push() {
local quiet="$1"
ShouldPush=1
if ! git_have_remote "$Origin" && [ -n "$Push" ]; then
[ -n "$quiet" ] || enote "L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine"
ShouldPush=
fi
[ -z "$ShouldPush" ] && Push=
}
function _push_branches() { function _push_branches() {
[ ${#push_branches[*]} -gt 0 ] || return [ ${#push_branches[*]} -gt 0 ] || return
[ -n "$Origin" ] || Origin=origin [ -n "$Origin" ] || Origin=origin

View File

@ -108,11 +108,17 @@ function set_interaction() {
# set_interaction en fonction des arguments de la ligne de commande. A utiliser # set_interaction en fonction des arguments de la ligne de commande. A utiliser
# de cette manière: # de cette manière:
# parse_opts ... "${PRETTYOPTS[@]}" @ args -- ... # parse_opts ... "${PRETTYOPTS[@]}" @ args -- ...
PRETTYOPTS=( # NB: ce n'est pas nécessaire, sauf si on veut afficher ces options dans l'aide
LOGTOOPTS=(
-L:,--log-to:LOGFILE '$elogto $value_' "++enregistrer les messages dans le fichier spécifié" -L:,--log-to:LOGFILE '$elogto $value_' "++enregistrer les messages dans le fichier spécifié"
)
VERBOSITYOPTS=(
-Q,--very-quiet,-q,--quiet,-v,--verbose,-D,--debug '$set_verbosity $option_' "++spécifier le niveau de verbiage" -Q,--very-quiet,-q,--quiet,-v,--verbose,-D,--debug '$set_verbosity $option_' "++spécifier le niveau de verbiage"
)
INTERACTIONOPTS=(
-b,--batch,-y,--automatic,-i,--interactive '$set_interaction $option_' "++spécifier le niveau d'interaction" -b,--batch,-y,--automatic,-i,--interactive '$set_interaction $option_' "++spécifier le niveau d'interaction"
) )
PRETTYOPTS=("${LOGTOOPTS[@]}" "${VERBOSITYOPTS[@]}" "${INTERACTIONOPTS[@]}")
function show_error() { [ "$__verbosity" -ge 1 ]; } function show_error() { [ "$__verbosity" -ge 1 ]; }
function show_warn() { [ "$__verbosity" -ge 2 ]; } function show_warn() { [ "$__verbosity" -ge 2 ]; }

29
bash/tests/test-interaction.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname -- "$0")/../src/nulib.sh" || exit 1
#NULIB_NO_DISABLE_SET_X=1
args=(
"tester diverses fonctions de saisie"
)
parse_args "$@"; set -- "${args[@]}"
estep "inter non auto non"
ask_yesno "oui ou non?" && echo oui || echo non
estep "inter oui auto oui"
ask_yesno "oui ou non?" O && echo oui || echo non
estep "inter non auto non"
ask_yesno "oui ou non?" N && echo oui || echo non
estep "inter non auto oui"
ask_yesno "oui ou non?" C && echo oui || echo non
estep "inter oui auto non"
ask_yesno "oui ou non?" X && echo oui || echo non
estep "valeur par défaut vide"
read_value "valeur" empty "" N; echo "valeur=$empty"
estep "valeur par défaut non vide"
read_value "valeur" default default N; echo "valeur=$default"
estep "valeur requise"
read_value "valeur" required; echo "valeur=$required"

View File

@ -7,7 +7,6 @@ Multiline=
Banner= Banner=
args=( args=(
"afficher divers messages avec les fonctions e*" "afficher divers messages avec les fonctions e*"
-D,--debug '$set_debug'
-d,--date NULIB_ELOG_DATE=1 -d,--date NULIB_ELOG_DATE=1
-m,--myname NULIB_ELOG_MYNAME=1 -m,--myname NULIB_ELOG_MYNAME=1
-n,--nc,--no-color '$__set_no_colors 1' -n,--nc,--no-color '$__set_no_colors 1'

24
bash/tests/test-verbosity.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname -- "$0")/../src/nulib.sh" || exit 1
#NULIB_NO_DISABLE_SET_X=1
args=(
"afficher divers messages avec les fonctions e*"
)
parse_args "$@"; set -- "${args[@]}"
eimportant "important (q)"
eattention "attention (q)"
eerror "error (q)"
ewarn "warn (q)"
enote "note (qv)"
einfo "info (qv)"
eecho "echo (qv)"
edebug "debug (D)"
estep "step (qv)"
estepe "stepe (qv)"
estepw "stepw (qv)"
estepn "stepn (qv)"
estepi "stepi (qv)"

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
exec "$(dirname -- "$0")/pdev" --tech-merge -Bdev82 dev74 "$@" exec "$(dirname -- "$0")/pdev" --tech-merge -Bdev82 dev74 -a "git checkout dev74" "$@"

View File

@ -0,0 +1,14 @@
#!/usr/bin/php
<?php
require __DIR__ . "/../vendor/autoload.php";
use nulib\tools\pman\ComposerFile;
use nulib\tools\pman\PmanYamlConfigFile;
use nulib\ValueException;
$composer = new ComposerFile();
$deps = $composer->getLocalDeps();
foreach ($deps as $dep => $path) {
echo "$path\n";
}

View File

@ -0,0 +1,22 @@
#!/usr/bin/php
<?php
require __DIR__ . "/../vendor/autoload.php";
use nulib\tools\pman\ComposerFile;
use nulib\tools\pman\PmanYamlConfigFile;
use nulib\ValueException;
$composer = new ComposerFile();
$config = new PmanYamlConfigFile();
if ($argc <= 1) {
throw new ValueException("Il faut spécifier le profil à sélectionner");
}
$profile = $argv[1];
$composer->selectProfile($profile, $config);
if (getenv("PMAN_COMPOSER_DEBUG")) {
$composer->print();
} else {
$composer->write();
}

34
bin/p
View File

@ -20,8 +20,18 @@ function git_status() {
fi fi
} }
function git_statuses() {
local cwd="$(pwd)" dir
for dir in "$@"; do
cd "$dir" || die
git_status --porcelain
cd "$cwd"
done
}
chdir= chdir=
all= all=
composer=
args=( args=(
"afficher l'état du dépôt" "afficher l'état du dépôt"
"[-d chdir] [-a patterns...] "[-d chdir] [-a patterns...]
@ -29,6 +39,7 @@ args=(
Si l'option -a est utilisée, ce script accepte comme arguments une liste de patterns permettant de filtrer les répertoires concernés" Si l'option -a est utilisée, ce script accepte comme arguments une liste de patterns permettant de filtrer les répertoires concernés"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-a,--all all=1 "faire l'opération sur tous les sous-répertoires de BASEDIR qui sont des dépôts git" -a,--all all=1 "faire l'opération sur tous les sous-répertoires de BASEDIR qui sont des dépôts git"
-r,--composer composer=1 "faire l'opération sur tous les projets composer dépendants"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -50,16 +61,23 @@ if [ -n "$all" ]; then
dirs+=("${dir%/.git}") dirs+=("${dir%/.git}")
done done
fi fi
setx cwd=pwd git_statuses "${dirs[@]}"
for dir in "${dirs[@]}"; do
cd "$dir" || die elif [ -n "$composer" ]; then
git_status --porcelain # projets dépendants
cd "$cwd" git_ensure_gitvcs
done setx toplevel=git_get_toplevel
cd "$toplevel" || die
setx cwd=ppath2 . "$OrigCwd"
[ -f composer.json ] || die "$cwd: ce n'est pas un projet composer"
setx -a dirs="$MYDIR/_pman-composer_local_deps.php"
git_statuses "${dirs[@]}"
else else
# répertoire courant uniquement # répertoire courant uniquement
setx toplevel=git_get_toplevel git_ensure_gitvcs
[ -n "$toplevel" ] && Cwd="$toplevel" Cwd="$(git_get_toplevel)"
args=() args=()
isatty || args+=(--porcelain) isatty || args+=(--porcelain)

125
bin/pdev
View File

@ -25,6 +25,9 @@ function ensure_branches() {
} }
function merge_action() { function merge_action() {
[ -z "$ShouldPush" ] && enote "\
L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine"
enote "\ enote "\
Ce script va Ce script va
- fusionner la branche ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} dans ${COULEUR_ROUGE}$DestBranch${COULEUR_NORMALE}${Push:+ - fusionner la branche ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} dans ${COULEUR_ROUGE}$DestBranch${COULEUR_NORMALE}${Push:+
@ -33,7 +36,7 @@ Ce script va
local script=".git/pman-merge.sh" local script=".git/pman-merge.sh"
local -a push_branches delete_branches local -a push_branches delete_branches
local after local hook
local comment= local comment=
local or_die=" || exit 1" local or_die=" || exit 1"
@ -44,17 +47,22 @@ Ce script va
if [ -n "\$merge" ]; then if [ -n "\$merge" ]; then
esection "Fusionner la branche" esection "Fusionner la branche"
EOF EOF
_mscript_merge_branch hook="BEFORE_MERGE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF
after="AFTER_MERGE_${SrcType^^}"; [ -n "${!after}" ] && _scripta <<EOF
( (
${!after} ${!hook}
)$or_die
EOF
_mscript_merge_branch
hook="AFTER_MERGE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF
(
${!hook}
)$or_die )$or_die
EOF EOF
_scripta <<EOF _scripta <<EOF
fi fi
EOF EOF
if [ -z "$ForbidDelete" ]; then if [ -n "$ShouldDelete" ]; then
_scripta <<EOF _scripta <<EOF
################################################################################ ################################################################################
# delete # delete
@ -62,9 +70,9 @@ if [ -n "\$delete" ]; then
esection "Supprimer la branche" esection "Supprimer la branche"
EOF EOF
_mscript_delete_branch _mscript_delete_branch
after="AFTER_DELETE_${SrcType^^}"; [ -n "${!after}" ] && _scripta <<EOF hook="AFTER_DELETE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF
( (
${!after} ${!hook}
)$or_die )$or_die
EOF EOF
_scripta <<EOF _scripta <<EOF
@ -77,6 +85,11 @@ EOF
# push # push
if [ -n "\$push" ]; then if [ -n "\$push" ]; then
esection "Pousser les branches" esection "Pousser les branches"
EOF
hook="BEFORE_PUSH_${DestType^^}"; [ -n "${!hook}" ] && _scripta <<EOF
(
${!hook}
)$or_die
EOF EOF
_script_push_branches _script_push_branches
if [ ${#delete_branches[*]} -gt 0 ]; then if [ ${#delete_branches[*]} -gt 0 ]; then
@ -85,35 +98,42 @@ EOF
_script_push_branches _script_push_branches
_scripta <<<fi _scripta <<<fi
fi fi
after="AFTER_PUSH_${DestType^^}"; [ -n "${!after}" ] && _scripta <<EOF hook="AFTER_PUSH_${DestType^^}"; [ -n "${!hook}" ] && _scripta <<EOF
( (
${!after} ${!hook}
)$or_die )$or_die
EOF EOF
_scripta <<EOF _scripta <<EOF
fi fi
EOF EOF
[ -n "$Delete" -o "$ForbidDelete" ] && Deleted=1 || Deleted= [ -n "$Delete" -o -z "$ShouldDelete" ] && Deleted=1 || Deleted=
[ -n "$Push" -o "$CantPush" ] && Pushed=1 || Pushed= [ -n "$ShouldDelete" -a -n "$Delete" ] && ShouldDelete=
if [ -n "$_NoRunScript" ]; then [ -n "$ShouldPush" -a -n "$Push" ] && ShouldPush=
einfo "Veuillez consulter le script $script pour le détail des opérations à effectuer" if [ -n "$_Fake" ]; then
cat "$script"
elif ! "$script" merge ${Delete:+delete} ${Push:+push}; then elif ! "$script" merge ${Delete:+delete} ${Push:+push}; then
eimportant "\ eimportant "\
Le script $script a été lancé avec les arguments 'merge${Delete:+ delete}${Push:+ push}' Le script $script a été lancé avec les arguments 'merge${Delete:+ delete}${Push:+ push}'
Veuillez le consulter pour le détail des opérations qui n'ont pas pu êtres effectuées" En cas d'erreur de merge, veuillez corriger les erreurs puis continuer avec
git merge --continue
Sinon, veuillez consulter le script et/ou le relancer
./$script${Delete:+ delete}${Push:+ push}"
die die
elif [ -n "$Deleted" -a -n "$Pushed" ]; then elif [ -n "$Deleted" -a -n "$Push" ]; then
[ -n "$_KeepScript" ] || rm "$script" [ -n "$_KeepScript" ] || rm "$script"
[ -n "$AfterMerge" ] && eval "$AfterMerge"
else else
local cmd local msg="\
[ -n "$Deleted" ] || cmd="$cmd
./$script delete"
[ -n "$Pushed" ] || cmd="$cmd
./$script push"
einfo "\
Le script $script a été lancé avec les arguments 'merge${Delete:+ delete}${Push:+ push}' Le script $script a été lancé avec les arguments 'merge${Delete:+ delete}${Push:+ push}'
Veuillez le consulter pour le détail des autres opérations à effectuer$cmd" Vous pouvez consulter le script et/ou le relancer
./$script${ShouldDelete:+ delete}${ShouldPush:+ push}"
[ -n "$AfterMerge" ] && msg="$msg
Il y a aussi les commandes supplémentaires suivantes:
${AfterMerge//
/
}"
einfo "$msg"
fi fi
} }
@ -125,16 +145,27 @@ chdir=
Origin= Origin=
ConfigBranch= ConfigBranch=
ConfigFile= ConfigFile=
_Fake=
_KeepScript= _KeepScript=
_NoRunScript=
action=merge action=merge
TechMerge= TechMerge=
SquashMsg= SquashMsg=
[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
[ -z "$PMAN_NO_DELETE" ] && Delete=1 || Delete= [ -z "$PMAN_NO_DELETE" ] && Delete=1 || Delete=
AfterMerge=
args=( args=(
"fusionner la branche source dans la branche destination correspondante" "fusionner la branche source dans la branche destination correspondante"
" [source]" " [source]
CONFIGURATION
Le fichier .pman.conf contient la configuration des branches. Les variables
supplémentaires suivantes peuvent être définies:
BEFORE_MERGE_<srcType>
AFTER_MERGE_<srcType>
AFTER_DELETE_<srcType>
BEFORE_PUSH_<destType>
AFTER_PUSH_<destType>
srcType et destType pouvant valoir UPSTREAM, DEVELOP, FEATURE, RELEASE, MAIN, HOTFIX, DIST"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine à partir de laquelle les branches distantes sont considérées" origine à partir de laquelle les branches distantes sont considérées"
@ -143,8 +174,8 @@ branche à partir de laquelle charger la configuration"
-c:,--config-file:CONFIG ConfigFile= "++\ -c:,--config-file:CONFIG ConfigFile= "++\
fichier de configuration des branches. cette option est prioritaire sur --config-branch fichier de configuration des branches. cette option est prioritaire sur --config-branch
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
--fake _Fake=1 "++option non documentée"
--keep-script _KeepScript=1 "++option non documentée" --keep-script _KeepScript=1 "++option non documentée"
--no-run-script _NoRunScript=1 "++option non documentée"
-w,--show action=show "\ -w,--show action=show "\
lister les modifications qui seraient fusionnées dans la branche destination" lister les modifications qui seraient fusionnées dans la branche destination"
-b,--rebase action=rebase "\ -b,--rebase action=rebase "\
@ -167,6 +198,10 @@ ne pas supprimer la branche après la fusion dans la destination"
--delete Delete=1 "++\ --delete Delete=1 "++\
supprimer la branche après la fusion dans la destination. supprimer la branche après la fusion dans la destination.
c'est l'option par défaut" c'est l'option par défaut"
-f,--force-merge ForceMerge=1 "++\
forcer la fusion pour une branche qui devrait être traitée par prel"
-a:,--after-merge AfterMerge= "\
évaluer le script spécifié après une fusion *réussie*"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -176,13 +211,7 @@ load_branches all
load_config "$MYNAME" load_config "$MYNAME"
load_branches current "$1" load_branches current "$1"
CantPush= resolve_should_push quiet
[ -n "$Origin" ] || Origin=origin
if ! git_have_remote "$Origin" && [ -n "$Push" ]; then
ewarn "L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine"
CantPush=1
fi
[ -n "$CantPush" ] && Push=
# puis faire l'action que l'on nous demande # puis faire l'action que l'on nous demande
case "$action" in case "$action" in
@ -192,24 +221,26 @@ show)
show_action "$@" show_action "$@"
;; ;;
merge) merge)
ForbidDelete= ShouldDelete=1
case "$SrcType" in no_merge_msg="$SrcBranch: cette branche doit être fusionnée dans $DestBranch avec prel"
develop|release|hotfix) if [ "$SrcType" == develop ]; then
die "$SrcBranch: cette branche doit être fusionnée dans $DestBranch avec prel" [ -z "$ForceMerge" ] && die "$no_merge_msg"
;; [ -n "$AfterMerge" ] || setx AfterMerge=qvals git checkout -q "$SrcBranch"
*) elif [ "$SrcType" == release -o "$SrcType" == hotfix ]; then
die "$no_merge_msg"
fi
# n'autoriser la suppression que pour feature # n'autoriser la suppression que pour feature
[ "$SrcType" == feature ] || ForbidDelete=1 [ "$SrcType" == feature ] || ShouldDelete=
;; [ -z "$ShouldDelete" ] && Delete=
esac [ -z "$_Fake" ] && git_ensure_cleancheckout
[ -n "$ForbidDelete" ] && Delete= if array_contains LocalBranches "$SrcBranch"; then
git_ensure_cleancheckout
if ! array_contains LocalBranches "$SrcBranch"; then
# si la branche source n'existe pas, la créer
exec "$MYDIR/pman" "$FEATURE${SrcBranch#$FEATURE}"
else
ensure_branches ensure_branches
merge_action "$@" merge_action "$@"
elif array_contains AllBranches "$SrcBranch"; then
enote "$SrcBranch: une branche du même nom existe dans l'origine"
die "$SrcBranch: branche locale introuvable"
else
die "$SrcBranch: branche introuvable"
fi fi
;; ;;
*) *)

144
bin/pman
View File

@ -34,16 +34,12 @@ function show_action() {
# Initialisation # Initialisation
################################################################################ ################################################################################
function init_repo_action() { function _init_config() {
[ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé" if [ ! -f .pman.conf -o -n "$ForceCreate" ]; then
local -a push_branches
if [ ! -f .pman.conf ]; then
ac_set_tmpfile config ac_set_tmpfile config
cp "$ConfigFile" "$config" cp "$ConfigFile" "$config"
"${EDITOR:-nano}" "$config" "${EDITOR:-nano}" "$config"
[ -s "$config" ] || exit_with ewarn "Initialisation du dépôt annulée" [ -s "$config" ] || return 1
cp "$config" .pman.conf cp "$config" .pman.conf
if testdiff .pman.conf "$ConfigFile"; then if testdiff .pman.conf "$ConfigFile"; then
@ -59,6 +55,15 @@ function init_repo_action() {
.*.swp" .*.swp"
git add .gitignore git add .gitignore
fi fi
return 0
}
function init_repo_action() {
local -a push_branches; local config
[ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé"
_init_config || exit_with ewarn "Initialisation du dépôt annulée"
einfo "Création de la branche $MAIN" einfo "Création de la branche $MAIN"
git symbolic-ref HEAD "refs/heads/$MAIN" git symbolic-ref HEAD "refs/heads/$MAIN"
@ -72,17 +77,55 @@ function init_repo_action() {
_push_branches _push_branches
} }
function init_develop_action() { function init_config_action() {
if [ -z "$DevelopBranch" ]; then local -a push_branches; config
[ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie"
[ -f .pman.conf -a -z "$ForceCreate" ] && die "La configuration pman a déjà été initialisée"
resolve_should_push
_init_config || exit_with ewarn "Initialisation de la configuration annulée"
git commit -m "configuration pman"
push_branches+=("$CurrentBranch")
_push_branches
}
function _ensure_main_branch() {
[ -n "$MAIN" ] || die "La branche MAIN n'a pas été définie" [ -n "$MAIN" ] || die "La branche MAIN n'a pas été définie"
[ -n "$MainBranch" ] || die "$MAIN: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" [ -n "$MainBranch" ] || die "$MAIN: cette branche n'existe pas (le dépôt a-t-il été initialisé?)"
}
function checkout_main_action() {
if [ -z "$MainBranch" ]; then
array_contains AllBranches "$MAIN" && exit_with enote "\
$MAIN: une branche du même nom existe dans l'origine
git checkout $MAIN"
_ensure_main_branch
fi
git checkout -q "$MAIN"
}
function _ensure_develop_branch() {
[ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie"
[ -n "$DevelopBranch" ] || die "$DEVELOP: cette branche n'existe pas (le dépôt a-t-il été initialisé?)"
}
function init_develop_action() {
local -a push_branches
if [ -z "$DevelopBranch" ]; then
array_contains AllBranches "$DEVELOP" && exit_with enote "\
$DEVELOP: une branche du même nom existe dans l'origine
git checkout $DEVELOP"
_ensure_main_branch
_ensure_develop_branch
resolve_should_push
enote "Vous allez créer la branche ${COULEUR_VERTE}$DEVELOP${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$MAIN${COULEUR_NORMALE}" enote "Vous allez créer la branche ${COULEUR_VERTE}$DEVELOP${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$MAIN${COULEUR_NORMALE}"
ask_yesno "Voulez-vous continuer?" O || die ask_yesno "Voulez-vous continuer?" O || die
local -a push_branches
einfo "Création de la branche $DEVELOP" einfo "Création de la branche $DEVELOP"
git checkout -b "$DEVELOP" "$MAIN" || die git checkout -b "$DEVELOP" "$MAIN" || die
push_branches+=("$DEVELOP") push_branches+=("$DEVELOP")
@ -92,17 +135,26 @@ function init_develop_action() {
git checkout -q "$DEVELOP" git checkout -q "$DEVELOP"
} }
function init_upstream_action() { function _ensure_upstream_branch() {
if [ -z "$UpstreamBranch" ]; then
[ -n "$UPSTREAM" ] || die "La branche UPSTREAM n'a pas été définie" [ -n "$UPSTREAM" ] || die "La branche UPSTREAM n'a pas été définie"
[ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie" [ -n "$UpstreamBranch" ] || die "$UPSTREAM: cette branche n'existe pas (le dépôt a-t-il été initialisé?)"
[ -n "$DevelopBranch" ] || die "$DEVELOP: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" }
function init_upstream_action() {
local -a push_branches; local config
if [ -z "$UpstreamBranch" ]; then
array_contains AllBranches "$UPSTREAM" && exit_with enote "\
$UPSTREAM: une branche du même nom existe dans l'origine
git checkout $UPSTREAM"
_ensure_develop_branch
_ensure_upstream_branch
resolve_should_push
enote "Vous allez créer la branche ${COULEUR_VERTE}$UPSTREAM${COULEUR_NORMALE}" enote "Vous allez créer la branche ${COULEUR_VERTE}$UPSTREAM${COULEUR_NORMALE}"
ask_yesno "Voulez-vous continuer?" O || die ask_yesno "Voulez-vous continuer?" O || die
local -a push_branches; local config
# faire une copie de la configuration actuelle # faire une copie de la configuration actuelle
ac_set_tmpfile config ac_set_tmpfile config
cp "$ConfigFile" "$config" cp "$ConfigFile" "$config"
@ -128,17 +180,26 @@ function init_upstream_action() {
git checkout -q "$UPSTREAM" git checkout -q "$UPSTREAM"
} }
function init_dist_action() { function _ensure_dist_branch() {
if [ -z "$DistBranch" ]; then
[ -n "$DIST" ] || die "La branche DIST n'a pas été définie" [ -n "$DIST" ] || die "La branche DIST n'a pas été définie"
[ -n "$MAIN" ] || die "La branche MAIN n'a pas été définie" [ -n "$DistBranch" ] || die "$DIST: cette branche n'existe pas (le dépôt a-t-il été initialisé?)"
[ -n "$MainBranch" ] || die "$MAIN: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" }
function init_dist_action() {
local -a push_branches
if [ -z "$DistBranch" ]; then
array_contains AllBranches "$DIST" && exit_with enote "\
$DIST: une branche du même nom existe dans l'origine
git checkout $DIST"
_ensure_main_branch
_ensure_dist_branch
resolve_should_push
enote "Vous allez créer la branche ${COULEUR_VERTE}$DIST${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$MAIN${COULEUR_NORMALE}" enote "Vous allez créer la branche ${COULEUR_VERTE}$DIST${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$MAIN${COULEUR_NORMALE}"
ask_yesno "Voulez-vous continuer?" O || die ask_yesno "Voulez-vous continuer?" O || die
local -a push_branches
einfo "Création de la branche $DIST" einfo "Création de la branche $DIST"
git checkout -b "$DIST" "$MAIN" || die git checkout -b "$DIST" "$MAIN" || die
push_branches+=("$DIST") push_branches+=("$DIST")
@ -149,18 +210,24 @@ function init_dist_action() {
} }
function init_feature_action() { function init_feature_action() {
local branch="${1#$FEATURE}" local -a push_branches; local branch
[ -n "$branch" ] || die "Vous devez définir la nom de la branche à créer"
[ -n "$FEATURE" ] || die "La branche FEATURE n'a pas été définie"
branch="${1#$FEATURE}"
[ -n "$branch" ] || die "Vous devez spécifier le nom de la branche"
branch="$FEATURE$branch" branch="$FEATURE$branch"
if ! array_contains AllBranches "$branch"; then
[ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie" if ! array_contains LocalBranches "$branch"; then
[ -n "$DevelopBranch" ] || die "$DEVELOP: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" array_contains AllBranches "$branch" && exit_with enote "\
$branch: une branche du même nom existe dans l'origine
git checkout $branch"
_ensure_develop_branch
resolve_should_push
enote "Vous allez créer la branche ${COULEUR_VERTE}$branch${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$DEVELOP${COULEUR_NORMALE}" enote "Vous allez créer la branche ${COULEUR_VERTE}$branch${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$DEVELOP${COULEUR_NORMALE}"
ask_yesno "Voulez-vous continuer?" O || die ask_yesno "Voulez-vous continuer?" O || die
local -a push_branches
einfo "Création de la branche $branch" einfo "Création de la branche $branch"
git checkout -b "$branch" "$DEVELOP" || die git checkout -b "$branch" "$DEVELOP" || die
push_branches+=("$branch") push_branches+=("$branch")
@ -174,7 +241,8 @@ function init_action() {
local what="${1:-develop}"; shift local what="${1:-develop}"; shift
case "$what" in case "$what" in
init|repo|r) init_repo_action "$@";; init|repo|r) init_repo_action "$@";;
main|m) git checkout -q "$MAIN";; config) init_config_action "$@";;
main|m) checkout_main_action;;
develop|dev|d) init_develop_action "$@";; develop|dev|d) init_develop_action "$@";;
upstream|up|u) init_upstream_action "$@";; upstream|up|u) init_upstream_action "$@";;
dist|x) init_dist_action "$@";; dist|x) init_dist_action "$@";;
@ -191,10 +259,11 @@ ConfigBranch=
ConfigFile= ConfigFile=
action=init action=init
Origin= Origin=
Push=1 [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
ForceCreate=
args=( args=(
"gérer un projet git" "gérer un projet git"
"repo|develop|upstream|dist "repo|config|develop|upstream|dist
INITIALISATION INITIALISATION
@ -219,6 +288,8 @@ fichier de configuration des branches. cette option est prioritaire sur --config
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
-w,--show-config action=show "++\ -w,--show-config action=show "++\
afficher la configuration chargée" afficher la configuration chargée"
--composer-select-profile action=composer_select_profile "\
sélectionner le profil composer spécifié en argument"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine vers laquelle pousser les branches" origine vers laquelle pousser les branches"
-n,--no-push Push= "\ -n,--no-push Push= "\
@ -226,6 +297,8 @@ ne pas pousser les branches vers leur origine après leur création"
--push Push=1 "++\ --push Push=1 "++\
pousser les branches vers leur origine après leur création. pousser les branches vers leur origine après leur création.
c'est l'option par défaut" c'est l'option par défaut"
-f,--force-create ForceCreate=1 "\
Avec config, forcer la (re)création du fichier .pman.conf"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -244,6 +317,9 @@ init)
git_ensure_cleancheckout git_ensure_cleancheckout
init_action "$@" init_action "$@"
;; ;;
composer_select_profile)
exec "$MYDIR/_pman-$action.php" "$@"
;;
*) *)
die "$action: action non implémentée" die "$action: action non implémentée"
;; ;;

View File

@ -42,6 +42,11 @@ function create_release_action() {
merge_hotfix_action "$@"; return $? merge_hotfix_action "$@"; return $?
fi fi
[ -n "$ManualRelease" ] && ewarn "\
L'option --no-merge a été forcée puisque ce dépôt ne supporte pas les releases automatiques"
[ -z "$ShouldPush" ] && enote "\
L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine"
if [ -z "$Version" -a -n "$CurrentVersion" -a -f VERSION.txt ]; then if [ -z "$Version" -a -n "$CurrentVersion" -a -f VERSION.txt ]; then
Version="$(<VERSION.txt)" Version="$(<VERSION.txt)"
Tag="$TAG_PREFIX$Version$TAG_SUFFIX" Tag="$TAG_PREFIX$Version$TAG_SUFFIX"
@ -80,6 +85,11 @@ Vous devrez:
# create # create
if [ -n "\$create" ]; then if [ -n "\$create" ]; then
esection "Création de la release" esection "Création de la release"
EOF
[ -n "$BEFORE_CREATE_RELEASE" ] && _scripta <<EOF
(
$BEFORE_CREATE_RELEASE
)$or_die
EOF EOF
_rscript_create_release_branch _rscript_create_release_branch
[ -n "$AFTER_CREATE_RELEASE" ] && _scripta <<EOF [ -n "$AFTER_CREATE_RELEASE" ] && _scripta <<EOF
@ -96,6 +106,11 @@ EOF
# merge # merge
if [ -n "\$merge" ]; then if [ -n "\$merge" ]; then
esection "Fusionner la release" esection "Fusionner la release"
EOF
[ -n "$BEFORE_MERGE_RELEASE" ] && _scripta <<EOF
(
$BEFORE_MERGE_RELEASE
)$or_die
EOF EOF
_rscript_merge_release_branch "$DestBranch" "$Tag" _rscript_merge_release_branch "$DestBranch" "$Tag"
_rscript_merge_release_branch "$SrcBranch" _rscript_merge_release_branch "$SrcBranch"
@ -114,6 +129,11 @@ EOF
# push # push
if [ -n "\$push" ]; then if [ -n "\$push" ]; then
esection "Pousser branches et tags" esection "Pousser branches et tags"
EOF
[ -n "$BEFORE_PUSH_RELEASE" ] && _scripta <<EOF
(
$BEFORE_PUSH_RELEASE
)$or_die
EOF EOF
_script_push_branches _script_push_branches
_script_push_tags _script_push_tags
@ -126,26 +146,25 @@ EOF
fi fi
EOF EOF
[ -n "$Merge" ] && Merged=1 || Merged= [ -z "$ManualRelease" -a -n "$Merge" ] && ShouldMerge= || ShouldMerge=1
[ -n "$Push" -o "$CantPush" ] && Pushed=1 || Pushed= [ -n "$ShouldPush" -a -n "$Push" ] && ShouldPush=
if [ -n "$_NoRunScript" ]; then if [ -n "$_Fake" ]; then
einfo "Veuillez consulter le script $script pour le détail des opérations à effectuer" cat "$script"
elif ! "$script" create ${Merge:+merge} ${Push:+push}; then elif ! "$script" create ${Merge:+merge} ${Push:+push}; then
eimportant "\ eimportant "\
Le script $script a été lancé avec les arguments 'create${Merge:+ merge}${Push:+ push}' Le script $script a été lancé avec les arguments 'create${Merge:+ merge}${Push:+ push}'
Veuillez le consulter pour le détail des opérations qui n'ont pas pu êtres effectuées" En cas d'erreur de merge, veuillez corriger les erreurs puis continuer avec
git merge --continue
Veuillez aussi consulter le script et/ou le relancer
./$script${Push:+ push}"
die die
elif [ -n "$Merged" -a -n "$Pushed" ]; then elif [ -n "$Merge" -a -n "$Push" ]; then
[ -n "$_KeepScript" ] || rm "$script" [ -n "$_KeepScript" ] || rm "$script"
else else
local cmd
[ -n "$Merged" ] || cmd="$cmd
./$script merge"
[ -n "$Pushed" ] || cmd="$cmd
./$script push"
einfo "\ einfo "\
Le script $script a été lancé avec les arguments 'create${Merge:+ merge}${Push:+ push}' Le script $script a été lancé avec les arguments 'create${Merge:+ merge}${Push:+ push}'
Veuillez le consulter pour le détail des autres opérations à effectuer$cmd" Vous pouvez consulter le script et/ou le relancer
./$script${ShouldMerge:+ merge}${ShouldPush:+ push}"
fi fi
} }
@ -172,8 +191,8 @@ chdir=
Origin= Origin=
ConfigBranch= ConfigBranch=
ConfigFile= ConfigFile=
_Fake=
_KeepScript= _KeepScript=
_NoRunScript=
action=release action=release
[ -z "$PMAN_NO_MERGE" ] && Merge=1 || Merge= [ -z "$PMAN_NO_MERGE" ] && Merge=1 || Merge=
[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
@ -182,7 +201,17 @@ CurrentVersion=
ForceCreate= ForceCreate=
args=( args=(
"faire une nouvelle release à partir de la branche source" "faire une nouvelle release à partir de la branche source"
" -v VERSION [source]" " -v VERSION [source]
CONFIGURATION
Le fichier .pman.conf contient la configuration des branches. Les variables
supplémentaires suivantes peuvent être définies:
BEFORE_CREATE_RELEASE
AFTER_CREATE_RELEASE
BEFORE_MERGE_RELEASE
AFTER_MERGE_RELEASE
BEFORE_PUSH_RELEASE
AFTER_PUSH_RELEASE"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine à partir de laquelle les branches distantes sont considérées" origine à partir de laquelle les branches distantes sont considérées"
@ -191,8 +220,8 @@ branche à partir de laquelle charger la configuration"
-c:,--config-file:CONFIG ConfigFile= "++\ -c:,--config-file:CONFIG ConfigFile= "++\
fichier de configuration des branches. cette option est prioritaire sur --config-branch fichier de configuration des branches. cette option est prioritaire sur --config-branch
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
--fake _Fake=1 "++option non documentée"
--keep-script _KeepScript=1 "++option non documentée" --keep-script _KeepScript=1 "++option non documentée"
--no-run-script _NoRunScript=1 "++option non documentée"
-w,--show action=show "\ -w,--show action=show "\
lister les modifications qui seraient intégrées dans la release" lister les modifications qui seraient intégrées dans la release"
--release action=release "++\ --release action=release "++\
@ -208,11 +237,11 @@ ne pas pousser les branches vers leur origine après la création de la release"
--push Push=1 "++\ --push Push=1 "++\
pousser les branches vers leur origine après la création de la release. pousser les branches vers leur origine après la création de la release.
c'est l'option par défaut" c'est l'option par défaut"
-v:,--version Version= "\ -v:,--version:VERSION Version= "\
spécifier la version de la release à créer" spécifier la version de la release à créer"
-C,--current-version CurrentVersion=1 "++\ -C,--current-version CurrentVersion=1 "++\
si aucune version n'est spécifiée, prendre la version présente dans le fichier VERSION.txt" si aucune version n'est spécifiée, prendre la version présente dans le fichier VERSION.txt"
-f:,--force-create ForceCreate= "\ -f,--force-create ForceCreate=1 "\
forcer la création de la release même si le tag correspond à la version existe déjà" forcer la création de la release même si le tag correspond à la version existe déjà"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -223,19 +252,11 @@ load_branches all
load_config "$MYNAME" load_config "$MYNAME"
load_branches current "$1"; shift load_branches current "$1"; shift
if [ -n "$Merge" -a -n "$NOAUTO" ]; then [ -n "$Merge" -a -n "$NOAUTO" ] && ManualRelease=1 || ManualRelease=
ewarn "L'option --no-merge a été forcée puisque ce dépôt ne supporte pas les releases automatiques" [ -n "$ManualRelease" ] && Merge=
Merge=
fi
[ -z "$Merge" ] && Push= [ -z "$Merge" ] && Push=
CantPush= resolve_should_push quiet
[ -n "$Origin" ] || Origin=origin
if ! git_have_remote "$Origin" && [ -n "$Push" ]; then
ewarn "L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine"
CantPush=1
fi
[ -n "$CantPush" ] && Push=
# puis faire l'action que l'on nous demande # puis faire l'action que l'on nous demande
case "$action" in case "$action" in
@ -245,7 +266,7 @@ show)
show_action "$@" show_action "$@"
;; ;;
release) release)
git_ensure_cleancheckout [ -z "$_Fake" ] && git_ensure_cleancheckout
ensure_branches ensure_branches
case "$SrcType" in case "$SrcType" in
release) merge_release_action "$@";; release) merge_release_action "$@";;

60
bin/pwip Executable file
View File

@ -0,0 +1,60 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname -- "$0")/../load.sh" || exit 1
require: git pman pman.conf
git_cleancheckout_DIRTY="\
Vous avez des modifications locales.
Enregistrez ces modifications avant de créer une nouvelle branche"
chdir=
Origin=
ConfigBranch=
ConfigFile=
[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
args=(
"créer une branche de feature"
"<feature>"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-O:,--origin Origin= "++\
origine à partir de laquelle les branches distantes sont considérées"
-B:,--config-branch ConfigBranch= "++\
branche à partir de laquelle charger la configuration"
-c:,--config-file:CONFIG ConfigFile= "++\
fichier de configuration des branches. cette option est prioritaire sur --config-branch
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
-n,--no-push Push= "\
ne pas pousser les branches vers leur origine après la fusion"
--push Push=1 "++\
pousser les branches vers leur origine après la fusion.
c'est l'option par défaut"
)
parse_args "$@"; set -- "${args[@]}"
# charger la configuration
ensure_gitdir "$chdir"
load_branches all
load_config "$MYNAME"
load_branches current
branch="$1"
if [ -z "$branch" -a ${#FeatureBranches[*]} -eq 1 ]; then
branch="${FeatureBranches[0]}"
fi
[ -n "$branch" ] || die "Vous devez spécifier la branche à créer"
branch="$FEATURE${branch#$FEATURE}"
resolve_should_push
git_ensure_cleancheckout
if array_contains AllBranches "$branch"; then
git checkout -q "$branch"
else
# si la branche source n'existe pas, la créer
args=(--origin "$Origin")
if [ -n "$ConfigFile" ]; then args+=(--config-file "$ConfigFile")
elif [ -n "$ConfigBranch" ]; then args+=(--config-branch "$ConfigBranch")
fi
[ -z "$Push" ] && args+=(--no-push)
exec "$MYDIR/pman" "${args[@]}" "$branch"
fi

View File

@ -25,7 +25,7 @@ COPY --from=builder /src/su-exec/su-exec /g/
RUN /g/build RUN /g/build
COPY --from=php /g/ /g/ COPY --from=php /g/ /g/
RUN /g/build -a @apache-php-cas php-utils RUN /g/build -a @php-apache-cas php-utils
EXPOSE 80 443 EXPOSE 80 443
ENTRYPOINT ["/g/entrypoint"] ENTRYPOINT ["/g/entrypoint"]

View File

@ -34,7 +34,7 @@ COPY --from=legacytools /g/ /g/
RUN /g/build nutools RUN /g/build nutools
COPY --from=php /g/ /g/ COPY --from=php /g/ /g/
RUN /g/build -a @apache-php-cas php-utils RUN /g/build -a @php-apache-cas php-utils
COPY --from=instantclient /g/ /g/ COPY --from=instantclient /g/ /g/
COPY --from=builder /opt/oracle/ /opt/oracle/ COPY --from=builder /opt/oracle/ /opt/oracle/

View File

@ -610,6 +610,42 @@ class cl {
############################################################################# #############################################################################
/**
* tester si $array a en début de tableau les mêmes clés que $ref, et dans le
* même ordre. $array peut avoir d'autres clés, ça n'influe pas sur le résultat
*
* $keys obtient la liste des clés de $ref trouvées, dans l'ordre de $array
* $remainKeys obtient la liste des clés de $array qui ne sont pas dans $ref
* $missingKeys obtient la liste des clés de $ref qui ne sont pas dans $array
*/
static function same_keys(?array $array, ?array $ref, ?array &$keys=null, ?array &$remainKeys=null, ?array &$missingKeys=null): bool {
$keys = [];
$remainKeys = [];
$missingKeys = [];
if ($array === null || $array === []) {
if ($ref === null || $ref === []) return true;
$missingKeys = array_keys($ref);
return false;
} elseif ($ref === null || $ref === []) {
$remainKeys = array_keys($array);
return true;
}
$refKeys = array_keys($ref);
$refCount = count($ref);
$index = 0;
$sameKeys = true;
foreach (array_keys($array) as $key) {
if ($index < $refCount) {
if ($key !== $refKeys[$index]) $sameKeys = false;
$index++;
}
if (array_key_exists($key, $ref)) $keys[] = $key;
else $remainKeys[] = $key;
}
$missingKeys = array_values(array_diff($refKeys, $keys));
return $sameKeys && $index == $refCount;
}
/** /**
* retourner le tableau $array en "renommant" les clés selon le tableau * retourner le tableau $array en "renommant" les clés selon le tableau
* $mappings qui contient des associations de la forme [$from => $to] * $mappings qui contient des associations de la forme [$from => $to]

View File

@ -2,7 +2,6 @@
namespace nulib\ext; namespace nulib\ext;
use Exception; use Exception;
use nulib\ext\json\JsonException;
use nulib\file; use nulib\file;
use nulib\os\IOException; use nulib\os\IOException;

View File

@ -6,7 +6,7 @@ class ref_schema {
const NATURE_METASCHEMA = [ const NATURE_METASCHEMA = [
"nature" => ["string", null, "nature du schéma", "nature" => ["string", null, "nature du schéma",
"pkey" => 0, "pkey" => 0,
"allowed_values" => ["assoc", "list", "scalar"], "allowed_values" => ["scalar", "assoc", "list"],
], ],
"title" => ["?string", null, "libellé de la valeur"], "title" => ["?string", null, "libellé de la valeur"],
"required" => ["bool", false, "la valeur est-elle requise?"], "required" => ["bool", false, "la valeur est-elle requise?"],
@ -31,9 +31,10 @@ class ref_schema {
"messages" => ["?array", null, "messages à afficher en cas d'erreur d'analyse"], "messages" => ["?array", null, "messages à afficher en cas d'erreur d'analyse"],
"formatter_func" => ["?callable", null, "fonction qui formatte la valeur pour affichage"], "formatter_func" => ["?callable", null, "fonction qui formatte la valeur pour affichage"],
"format" => [null, null, "format à utiliser pour l'affichage"], "format" => [null, null, "format à utiliser pour l'affichage"],
"" => ["array", "scalar", "nature du schéma", "" => ["array", ["scalar"], "nature du schéma",
"" => ["assoc", "schema" => self::NATURE_METASCHEMA], "schema" => self::NATURE_METASCHEMA,
], ],
"schema" => ["?array", null, "schéma de la valeur si c'est un array"],
"name" => ["?string", null, "identifiant de la valeur"], "name" => ["?string", null, "identifiant de la valeur"],
"pkey" => ["?pkey", null, "chemin de clé de la valeur dans un tableau associatif"], "pkey" => ["?pkey", null, "chemin de clé de la valeur dans un tableau associatif"],
"header" => ["?string", null, "nom de l'en-tête s'il faut présenter cette donnée dans un tableau"], "header" => ["?string", null, "nom de l'en-tête s'il faut présenter cette donnée dans un tableau"],

View File

@ -6,5 +6,6 @@ class ref_types {
"boolean" => "bool", "boolean" => "bool",
"integer" => "int", "integer" => "int",
"flt" => "float", "double" => "float", "dbl" => "float", "flt" => "float", "double" => "float", "dbl" => "float",
"func" => "callable", "function" => "callable",
]; ];
} }

View File

@ -0,0 +1,172 @@
<?php
namespace nulib\tools\pman;
use nulib\cl;
use nulib\ext\json;
use nulib\file;
use nulib\os\path;
use nulib\ValueException;
class ComposerFile {
function __construct(string $composerFile=".", bool $ensureExists=true) {
if (is_dir($composerFile)) $composerFile = path::join($composerFile, 'composer.json');
if ($ensureExists && !file_exists($composerFile)) {
$message = path::ppath($composerFile).": fichier introuvable";
throw new ValueException($message);
}
$this->composerFile = $composerFile;
$this->load();
}
protected string $composerFile;
function getComposerFile(): string {
return $this->composerFile;
}
protected ?array $data = null;
protected function load(): array {
if ($this->data === null) {
$this->data = json::load($this->composerFile);
}
return $this->data;
}
function getv(string $pkey="", $default=null) {
return cl::pget($this->data, $pkey, $default);
}
function geta(string $pkey="", ?array $default=[]): ?array {
return cl::withn($this->getv($pkey, $default));
}
function getRequires(): array {
return $this->geta("require");
}
function setRequire(string $dep, string $version): void {
$this->setPkey("require.$dep", $version);
}
function getRequireDevs(): array {
return $this->geta("require-dev");
}
function setRequireDev(string $dep, string $version): void {
$this->setPkey("require-dev.$dep", $version);
}
function getRepositories(): array {
return $this->geta("repositories");
}
function setRepositories(array $repositories): void {
$this->data["repositories"] = $repositories;
}
function setPkey(string $pkey, $value): void {
cl::pset($this->data, $pkey, $value);
}
function delPkey(string $pkey): void {
cl::pdel($this->data, $pkey);
}
const PATHS = [
"nulib/php" => "nulib",
];
function selectProfile(string $profile, PmanYamlConfigFile $config): void {
$config = $config->getProfileConfig($profile);
// corriger les liens
$deps = cl::merge(array_keys($config["require"]), array_keys($config["require-dev"]));
$paths = [];
foreach ($deps as $dep) {
$path = cl::get(self::PATHS, $dep, $dep);
$path = str_replace("/", "-", $path);
$path = "../$path";
$paths[$dep] = $path;
}
if ($config["link"]) {
// Ajouter les liens
$adds = [];
$repositories = $this->getRepositories();
foreach ($deps as $dep) {
$found = false;
foreach ($repositories as $repository) {
if ($repository["type"] === "path" && $repository["url"] === $paths[$dep]) {
$found = true;
break;
}
}
if (!$found) {
$adds[] = [
"type" => "path",
"url" => $paths[$dep],
];
}
}
if ($adds) {
$this->setRepositories(cl::merge($adds, $repositories));
}
} else {
// Supprimer les liens
$dels = [];
$repositories = $this->getRepositories();
foreach ($deps as $dep) {
foreach ($repositories as $key => $repository) {
if ($repository["type"] === "path" && $repository["url"] === $paths[$dep]) {
$dels[] = $key;
break;
}
}
}
if ($dels) {
foreach (array_reverse($dels) as $key) {
unset($repositories[$key]);
}
$this->setRepositories(array_values($repositories));
}
}
// corriger les versions
foreach ($config["require"] as $dep => $version) {
$this->data["require"][$dep] = $version;
}
foreach ($config["require-dev"] as $dep => $version) {
$this->data["require-dev"][$dep] = $version;
}
}
function getLocalDeps(): array {
$deps = cl::merge(array_keys($this->getRequires()), array_keys($this->getRequireDevs()));
$paths = [];
foreach ($deps as $dep) {
$path = cl::get(self::PATHS, $dep, $dep);
$path = str_replace("/", "-", $path);
$path = "../$path";
$paths[$dep] = $path;
}
$repositories = $this->getRepositories();
$localDeps = [];
foreach ($deps as $dep) {
foreach ($repositories as $key => $repository) {
if ($repository["type"] === "path" && $repository["url"] === $paths[$dep]) {
$localDeps[$dep] = $repository["url"];
break;
}
}
}
return $localDeps;
}
function print(): void {
$contents = json::with($this->data, json::INDENT_TABS);
if ($contents) echo "$contents\n";
}
function write(): void {
$contents = json::with($this->data, json::INDENT_TABS);
file::writer($this->composerFile)->putContents("$contents\n");
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace nulib\tools\pman;
use nulib\A;
use nulib\ext\yaml;
use nulib\os\path;
use nulib\ValueException;
class PmanYamlConfigFile {
function __construct(string $configFile=".", bool $ensureExists=true) {
if (is_dir($configFile)) $configFile = path::join($configFile, '.pman.yml');
if ($ensureExists && !file_exists($configFile)) {
$message = path::ppath($configFile).": fichier introuvable";
throw new ValueException($message);
}
$this->configFile = $configFile;
$this->load();
}
protected string $configFile;
function getConfigFile(): string {
return $this->configFile;
}
protected ?array $data = null;
protected function load(): array {
if ($this->data === null) {
$data = yaml::load($this->configFile);
$composer =& $data["composer"];
A::ensure_array($composer);
A::ensure_array($composer["profiles"]);
foreach ($composer["profiles"] as $profileName) {
$profile =& $composer[$profileName];
A::ensure_array($profile);
$profile["link"] = boolval($profile["link"] ?? false);
A::ensure_array($profile["require"]);
A::ensure_array($profile["require-dev"]);
}
$this->data = $data;
}
return $this->data;
}
function getProfileConfig(string $profile): array {
$config = $this->data["composer"][$profile] ?? null;
if ($config === null) {
throw new ValueException("$profile: profil invalide");
}
return $config;
}
function print(): void {
yaml::dump($this->data);
}
}

37
php/tests/clTest.php Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace nulib;
use nulib\tests\TestCase;
class clTest extends TestCase {
function checkKeys(?array $array, ?array $ref, bool $sameKeys, array $expectedKeys, array $expectedRemains, array $expectedMissings): void {
self::assertSame($sameKeys, cl::same_keys($array, $ref, $keys, $remains, $missings), "sameKeys");
self::assertSame($expectedKeys, $keys, "keys");
self::assertSame($expectedRemains, $remains, "remains");
self::assertSame($expectedMissings, $missings, "missings");
}
function test_same_keys() {
$array = ["a" => 42, "b" => "tesxt"]; $arrayKeys = array_keys($array);
$xarray = ["parasite0", "a" => 42, "parasite1", "b" => "tesxt"]; $xarrayKeys = array_keys($array);
$ref = ["a" => "int", "b" => "text"]; $refKeys = array_keys($ref);
$missingArray = ["c" => true]; $missingKeys = array_keys($missingArray);
$missingRef = ["c" => "bool"]; $missingKeys = array_keys($missingRef);
$this->checkKeys(null, null, true, [], [], []);
$this->checkKeys(null, [], true, [], [], []);
$this->checkKeys([], null, true, [], [], []);
$this->checkKeys([], [], true, [], [], []);
$this->checkKeys(null, $ref, false, [], [], $refKeys);
$this->checkKeys([], $ref, false, [], [], $refKeys);
$this->checkKeys($array, null, true, [], $arrayKeys, []);
$this->checkKeys($array, [], true, [], $arrayKeys, []);
$this->checkKeys($array, $ref, true, $arrayKeys, [], []);
$this->checkKeys(cl::merge($array, $missingArray), $ref, true, $arrayKeys, $missingKeys, []);
$this->checkKeys($array, cl::merge($ref, $missingRef), false, $arrayKeys, [], $missingKeys);
$this->checkKeys($xarray, $ref, false, $arrayKeys, [0, 1], []);
}
}

View File

@ -1,67 +0,0 @@
<?php
namespace nulib\php\access;
use nulib\tests\TestCase;
use nulib\wip\php\access\KeyAccess;
use stdClass;
class KeyAccessTest extends TestCase {
function testAccess() {
$default = new stdClass();
$array = ["null" => null, "false" => false, "empty" => ""];
#
$a = new KeyAccess($array, "inexistant");
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
$a = new KeyAccess($array, "false");
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$a = new KeyAccess($array, "null", ["allow_null" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null", ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$a = new KeyAccess($array, "false", ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "false", ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$a = new KeyAccess($array, "empty", ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty", ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
}

View File

@ -1,70 +0,0 @@
<?php
namespace nulib\php\access;
use nulib\tests\TestCase;
use nulib\wip\php\access\ValueAccess;
use stdClass;
class ValueAccessTest extends TestCase {
function testAccess() {
$default = new stdClass();
#
$i = null;
$a = new ValueAccess($i);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new ValueAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
$i = "";
$a = new ValueAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$i = null;
$a = new ValueAccess($i, ["allow_null" => false]);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = null;
$a = new ValueAccess($i, ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$i = false;
$a = new ValueAccess($i, ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new ValueAccess($i, ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$i = "";
$a = new ValueAccess($i, ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = "";
$a = new ValueAccess($i, ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
}

View File

@ -1,40 +0,0 @@
<?php
namespace nulib\php\content;
use nulib\php\content\impl\html;
use nulib\wip\web\content\v;
use PHPUnit\Framework\TestCase;
class cTest extends TestCase {
function testTo_string() {
self::assertSame("", c::to_string(null));
self::assertSame("", c::to_string(false));
self::assertSame("pouet&lt;q/&gt;", c::to_string("pouet<q/>"));
self::assertSame("pouet<q/>", c::to_string(["pouet<q/>"]));
self::assertSame("hello world", c::to_string(["hello", "world"]));
self::assertSame("hello1 world", c::to_string(["hello1", "world"]));
self::assertSame("hello<world>", c::to_string(["hello", "<world>"]));
self::assertSame("<hello>world", c::to_string(["<hello>", "world"]));
self::assertSame("hello,world", c::to_string(["hello,", "world"]));
self::assertSame("hello&nbsp;world", c::to_string(["hello&nbsp;", "world"]));
self::assertSame("hello. world", c::to_string(["hello.", "world"]));
self::assertSame("hello.<world>", c::to_string(["hello.", "<world>"]));
self::assertSame(
"<h1>title&lt;q/&gt;</h1><p>hello<nq/><span>brave&lt;q/&gt;</span><span>world<nq/></span></p>",
c::to_string([
[html::H1, "title<q/>"],
[html::P, [
"hello<nq/>",
[html::SPAN, "brave<q/>"],
[html::SPAN, ["world<nq/>"]],
]],
]));
}
function testXxx() {
$content = [[v::h1, "hello"]];
self::assertSame("<h1>hello</h1>", c::to_string($content));
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace nulib\php\content\impl;
use nulib\php\content\IContent;
class AContent implements IContent {
function getContent(): iterable {
return ["<span>content</span>"];
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace nulib\php\content\impl;
use nulib\php\content\IPrintable;
class APrintable implements IPrintable {
function print(): void {
echo "<p>printable</p>";
}
}

View File

@ -1,23 +0,0 @@
<?php
namespace nulib\php\content\impl;
use nulib\php\content\c;
use nulib\php\content\IContent;
class ATag implements IContent {
function __construct(string $tag, $content=null) {
$this->tag = $tag;
$this->content = $content;
}
protected $tag;
protected $content;
function getContent(): iterable {
return [
"<$this->tag>",
...c::q($this->content),
"</$this->tag>",
];
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace nulib\php\content\impl;
class html {
const H1 = [self::class, "h1"];
const DIV = [self::class, "div"];
const P = [self::class, "p"];
const SPAN = [self::class, "span"];
static function h1($content) { return new ATag("h1", $content); }
static function div($content) { return new ATag("div", $content); }
static function p($content) { return new ATag("p", $content); }
static function span($content) { return new ATag("span", $content); }
}

View File

@ -1,64 +0,0 @@
<?php
namespace nulib\schema\_scalar;
use nulib\tests\TestCase;
use nulib\wip\schema\_scalar\ScalarSchema;
use nulib\wip\schema\SchemaException;
class ScalarSchemaTest extends TestCase {
const NULL_SCHEMA = [
"type" => [null],
"default" => null,
"title" => null,
"required" => false,
"nullable" => true,
"desc" => null,
"analyzer_func" => null,
"extractor_func" => null,
"parser_func" => null,
"normalizer_func" => null,
"messages" => null,
"formatter_func" => null,
"format" => null,
"" => ["scalar"],
"name" => null,
"pkey" => null,
"header" => null,
"composite" => null,
];
static function schema(array $schema): array {
return array_merge(self::NULL_SCHEMA, $schema);
}
function testNormalize() {
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize(null));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([]));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([null]));
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize([[]]);
});
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize([[null]]);
});
$string = self::schema(["type" => ["string"], "nullable" => false]);
self::assertSame($string, ScalarSchema::normalize("string"));
self::assertSame($string, ScalarSchema::normalize(["string"]));
$nstring = self::schema(["type" => ["string"]]);
self::assertSame($nstring, ScalarSchema::normalize(["?string"]));
self::assertSame($nstring, ScalarSchema::normalize(["?string|null"]));
self::assertSame($nstring, ScalarSchema::normalize(["string|null"]));
self::assertSame($nstring, ScalarSchema::normalize([["?string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize([["string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize([["string", null]]));
$key = self::schema(["type" => ["string", "int"], "nullable" => false]);
self::assertSame($key, ScalarSchema::normalize("string|int"));
$nkey = self::schema(["type" => ["string", "int"], "nullable" => true]);
self::assertSame($nkey, ScalarSchema::normalize("?string|int"));
self::assertSame($nkey, ScalarSchema::normalize("string|?int"));
}
}

View File

@ -1,111 +0,0 @@
<?php
namespace nulib\schema\types;
use Exception;
use nulib\tests\TestCase;
use nulib\schema\_scalar\ScalarValue;
use nulib\schema\Schema;
class boolTest extends TestCase {
function commonTests($destv, &$dest, callable $destvSetter): void {
$destv->set(true);
self::assertSame(true, $destv->get());
self::assertSame(true, $dest);
self::assertSame("Oui", $destv->format());
self::assertSame("Oui", $destv->format("OuiNonNull"));
self::assertSame("O", $destv->format("ON"));
self::assertSame("O", $destv->format("ONN"));
$destv->set(false);
self::assertSame(false, $destv->get());
self::assertSame(false, $dest);
self::assertSame("Non", $destv->format());
self::assertSame("Non", $destv->format("OuiNonNull"));
self::assertSame("N", $destv->format("ON"));
self::assertSame("N", $destv->format("ONN"));
$destv->set("yes");
self::assertSame(true, $destv->get());
$destv->set(" yes ");
self::assertSame(true, $destv->get());
$destv->set("12");
self::assertSame(true, $destv->get());
$destv->set(12);
self::assertSame(true, $destv->get());
$destv->set("no");
self::assertSame(false, $destv->get());
$destv->set(" no ");
self::assertSame(false, $destv->get());
$destv->set("0");
self::assertSame(false, $destv->get());
$destv->set(0);
self::assertSame(false, $destv->get());
$destv->set(12.34);
self::assertSame(true, $destv->get());
self::assertException(Exception::class, $destvSetter("a"));
self::assertException(Exception::class, $destvSetter([]));
self::assertException(Exception::class, $destvSetter(["a"]));
}
function testBool() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "bool");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
self::assertException(Exception::class, $destvSetter(""));
self::assertException(Exception::class, $destvSetter(" "));
$this->commonTests($destv, $dest, $destvSetter);
}
function testNbool() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "?bool");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("Non", $destv->format());
self::assertSame("", $destv->format("OuiNonNull"));
self::assertSame("N", $destv->format("ON"));
self::assertSame("", $destv->format("ONN"));
$destv->set("");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("Non", $destv->format());
self::assertSame("", $destv->format("OuiNonNull"));
self::assertSame("N", $destv->format("ON"));
self::assertSame("", $destv->format("ONN"));
$destv->set(" ");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("Non", $destv->format());
self::assertSame("", $destv->format("OuiNonNull"));
self::assertSame("N", $destv->format("ON"));
self::assertSame("", $destv->format("ONN"));
$this->commonTests($destv, $dest, $destvSetter);
}
}

View File

@ -1,139 +0,0 @@
<?php
namespace nulib\schema\types;
use Exception;
use nulib\tests\TestCase;
use nulib\schema\_scalar\ScalarValue;
use nulib\schema\Schema;
class floatTest extends TestCase {
function commonTests($destv, &$dest, callable $destvSetter): void {
$destv->set(12);
self::assertSame(12.0, $destv->get());
self::assertSame(12.0, $dest);
self::assertSame("12", $destv->format());
self::assertSame("0012", $destv->format("%04u"));
$destv->set("12");
self::assertSame(12.0, $destv->get());
$destv->set(" 12 ");
self::assertSame(12.0, $destv->get());
$destv->set(12.34);
self::assertSame(12.34, $destv->get());
$destv->set(true);
self::assertSame(1.0, $destv->get());
self::assertException(Exception::class, $destvSetter("a"));
self::assertException(Exception::class, $destvSetter([]));
self::assertException(Exception::class, $destvSetter(["a"]));
}
function testFloat() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "float");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
self::assertException(Exception::class, $destvSetter(""));
self::assertException(Exception::class, $destvSetter(" "));
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredFloat() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"float", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
self::assertException(Exception::class, $destvSetter(""));
self::assertException(Exception::class, $destvSetter(" "));
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
function testNfloat() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "?float");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set("");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set(" ");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredNfloat() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"?float", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set("");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set(" ");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
}

View File

@ -1,139 +0,0 @@
<?php
namespace nulib\schema\types;
use Exception;
use nulib\tests\TestCase;
use nulib\schema\_scalar\ScalarValue;
use nulib\schema\Schema;
class intTest extends TestCase {
function commonTests($destv, &$dest, callable $destvSetter): void {
$destv->set(12);
self::assertSame(12, $destv->get());
self::assertSame(12, $dest);
self::assertSame("12", $destv->format());
self::assertSame("0012", $destv->format("%04u"));
$destv->set("12");
self::assertSame(12, $destv->get());
$destv->set(" 12 ");
self::assertSame(12, $destv->get());
$destv->set(12.34);
self::assertSame(12, $destv->get());
$destv->set(true);
self::assertSame(1, $destv->get());
self::assertException(Exception::class, $destvSetter("a"));
self::assertException(Exception::class, $destvSetter([]));
self::assertException(Exception::class, $destvSetter(["a"]));
}
function testInt() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "int");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
self::assertException(Exception::class, $destvSetter(""));
self::assertException(Exception::class, $destvSetter(" "));
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredInt() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"int", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
self::assertException(Exception::class, $destvSetter(""));
self::assertException(Exception::class, $destvSetter(" "));
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
function testNint() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "?int");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set("");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set(" ");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredNint() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"?int", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set("");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
$destv->set(" ");
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
}

View File

@ -1,123 +0,0 @@
<?php
namespace nulib\schema\types;
use Exception;
use nulib\tests\TestCase;
use nulib\wip\schema\_scalar\ScalarValue;
use nulib\wip\schema\Schema;
class strTest extends TestCase {
function commonTests($destv, &$dest, callable $destvSetter): void {
$destv->set("");
self::assertSame("", $destv->get());
self::assertSame("", $dest);
$destv->set(" ");
self::assertSame(" ", $destv->get());
self::assertSame(" ", $dest);
$destv->set("a");
self::assertSame("a", $destv->get());
self::assertSame("a", $dest);
$destv->set("12");
self::assertSame("12", $destv->get());
$destv->set(" 12 ");
self::assertSame(" 12 ", $destv->get());
$destv->set(12);
self::assertSame("12", $destv->get());
$destv->set(12.34);
self::assertSame("12.34", $destv->get());
$destv->set(true);
self::assertSame("1", $destv->get());
self::assertException(Exception::class, $destvSetter([]));
self::assertException(Exception::class, $destvSetter(["a"]));
}
function testStr() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "string");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredStr() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"string", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
self::assertException(Exception::class, $destvSetter(null));
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
function testNstr() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, "?string");
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur non requise donc retourne null
$destv->set(false);
self::assertNull($destv->get());
$this->commonTests($destv, $dest, $destvSetter);
}
function testRequiredNstr() {
/** @var ScalarValue $destv */
Schema::nv($destv, $dest, null, $schema, [
"?string", null,
"required" => true,
]);
$destvSetter = function($value) use($destv) {
return function() use($destv, $value) {
$destv->set($value);
};
};
$destv->set(null);
self::assertNull($destv->get());
self::assertNull($dest);
self::assertSame("", $destv->format());
// valeur requise donc lance une exception
self::assertException(Exception::class, $destvSetter(false));
$this->commonTests($destv, $dest, $destvSetter);
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace nulib\schema\types;
use nulib\tests\TestCase;
use nulib\schema\_scalar\ScalarValue;
use nulib\schema\Schema;
class unionTest extends TestCase {
function testUnionTypes() {
## l'ordre des types doit être respecté
# string puis int
/** @var ScalarValue $siv */
Schema::nv($siv, $si, null, $sis, "string|int");
$siv->set("12");
self::assertSame("12", $si);
$siv->set(12);
self::assertSame(12, $si);
# int puis string
Schema::nv($isv, $is, null, $iss, "int|string");
$isv->set("12");
self::assertSame("12", $is);
$isv->set(12);
self::assertSame(12, $is);
}
}

View File

@ -455,6 +455,9 @@ OPTIONS
function host_docker_run() { function host_docker_run() {
# lancer une commande avec docker # lancer une commande avec docker
if [ "$1" == composer ]; then
: # pas d'analyse d'argument pour composer
else
SOPTS=+w: SOPTS=+w:
LOPTS=help,chdir:,no-use-rslave LOPTS=help,chdir:,no-use-rslave
args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
@ -498,6 +501,7 @@ OPTIONS
esac esac
shift shift
done done
fi
args=( args=(
run -it --rm run -it --rm
@ -573,6 +577,9 @@ function container_exec() {
fi fi
fi fi
if [ "$1" == composer ]; then
: # pas d'analyse d'argument pour composer
else
SOPTS=+w: SOPTS=+w:
LOPTS=chdir: LOPTS=chdir:
args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args"
@ -587,6 +594,7 @@ function container_exec() {
esac esac
shift shift
done done
fi
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
die "no command specified" die "no command specified"

Binary file not shown.