diff --git a/CHANGES.md b/CHANGES.md index e65c7a6..5332e13 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,31 @@ +## 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.4p74 du 01/03/2025-06:22 diff --git a/VERSION.txt b/VERSION.txt index 42045ac..1d0ba9e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.3.4 +0.4.0 diff --git a/bash/src/_output_color.sh b/bash/src/_output_color.sh index ce0dd77..afe6428 100644 --- a/bash/src/_output_color.sh +++ b/bash/src/_output_color.sh @@ -6,15 +6,15 @@ function __esection() { local length="${COLUMNS:-80}" setx lsep=__complete "$prefix" "$length" - - tooenc "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" + recho "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" [ -n "$*" ] || return 0 length=$((length - 1)) setx -a lines=echo "$1" for line in "${lines[@]}"; do setx line=__complete "$prefix- $line" "$length" - tooenc "$COULEUR_BLEUE$line-$COULEUR_NORMALE" + recho "$COULEUR_BLEUE$line-$COULEUR_NORMALE" done - tooenc "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" + recho "$COULEUR_BLEUE$lsep$COULEUR_NORMALE" } function __etitle() { local -a lines; local maxlen=0 @@ -23,10 +23,10 @@ function __etitle() { setx -a lines=echo "$1" for line in "${lines[@]}"; do [ ${#line} -gt $maxlen ] && maxlen=${#line} - tooenc "${prefix}${COULEUR_BLEUE}T $line$COULEUR_NORMALE" + recho "${prefix}${COULEUR_BLEUE}T $line$COULEUR_NORMALE" done maxlen=$((maxlen + 2)) - tooenc "${prefix}${COULEUR_BLEUE}T$(__complete "" $maxlen -)${COULEUR_NORMALE}" + recho "${prefix}${COULEUR_BLEUE}T$(__complete "" $maxlen -)${COULEUR_NORMALE}" } function __edesc() { local -a lines @@ -34,7 +34,7 @@ function __edesc() { setx -a lines=echo "$1" for line in "${lines[@]}"; do - tooenc "${prefix}${COULEUR_BLEUE}>${COULEUR_NORMALE} $line" + recho "${prefix}${COULEUR_BLEUE}>${COULEUR_NORMALE} $line" done } function __ebanner() { @@ -43,35 +43,35 @@ function __ebanner() { local length="${COLUMNS:-80}" setx lsep=__complete "$prefix" "$length" = - tooenc "$COULEUR_ROUGE$lsep" + recho "$COULEUR_ROUGE$lsep" length=$((length - 1)) setx -a lines=echo "$1" for line in "" "${lines[@]}" ""; do setx line=__complete "$prefix= $line" "$length" - tooenc "$line=" + recho "$line=" done - tooenc "$lsep$COULEUR_NORMALE" + recho "$lsep$COULEUR_NORMALE" } -function __eimportant() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}!${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __eattention() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}*${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __eerror() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}E${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __ewarn() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}W${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __enote() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}N${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __einfo() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLEUE}I${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __edebug() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLANCHE}D${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __eimportant() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}!${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __eattention() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}*${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __eerror() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}E${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __ewarn() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}W${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __enote() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}N${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __einfo() { recho "$(__edate)$(__eindent0)${COULEUR_BLEUE}I${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 __estepe() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepw() { tooenc "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepn() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepi() { tooenc "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estep_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepe_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepw_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepn_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __estepi_() { tooenc_ "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estep() { recho "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepe() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepw() { recho "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepn() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepi() { recho "$(__edate)$(__eindent0)${COULEUR_BLEUE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estep_() { recho_ "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepe_() { recho_ "$(__edate)$(__eindent0)${COULEUR_ROUGE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepw_() { recho_ "$(__edate)$(__eindent0)${COULEUR_JAUNE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __estepn_() { recho_ "$(__edate)$(__eindent0)${COULEUR_VERTE}.${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 __asuccess() { tooenc "$(__edate)$(__eindent0)${COULEUR_VERTE}✔${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __afailure() { tooenc "$(__edate)$(__eindent0)${COULEUR_ROUGE}✘${COULEUR_NORMALE} $(__eindent "$1" " ")"; } -function __adone() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } +function __action() { recho "$(__edate)$(__eindent0)${COULEUR_BLANCHE}.${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __asuccess() { recho "$(__edate)$(__eindent0)${COULEUR_VERTE}✔${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __afailure() { recho "$(__edate)$(__eindent0)${COULEUR_ROUGE}✘${COULEUR_NORMALE} $(__eindent "$1" " ")"; } +function __adone() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; } diff --git a/bash/src/_output_vanilla.sh b/bash/src/_output_vanilla.sh index c37509d..cbd466f 100644 --- a/bash/src/_output_vanilla.sh +++ b/bash/src/_output_vanilla.sh @@ -6,23 +6,23 @@ function __esection() { local length="${COLUMNS:-80}" setx lsep=__complete "$prefix" "$length" - - tooenc "$lsep" + recho "$lsep" [ -n "$*" ] || return 0 length=$((length - 1)) setx -a lines=echo "$1" for line in "${lines[@]}"; do setx line=__complete "$prefix- $line" "$length" - tooenc "$line-" + recho "$line-" done - tooenc "$lsep" + recho "$lsep" } function __etitle() { local p="TITLE: " i=" " - tooenc "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" + recho "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" } function __edesc() { local p="DESC: " i=" " - tooenc "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" + recho "$(__edate)$(__eindent0)${p}$(__eindent "$1" "$i")" } function __ebanner() { local -a lines @@ -30,37 +30,37 @@ function __ebanner() { local length="${COLUMNS:-80}" setx lsep=__complete "$prefix" "$length" = - tooenc "$lsep" + recho "$lsep" length=$((length - 1)) setx -a lines=echo "$1" for line in "" "${lines[@]}" ""; do setx line=__complete "$prefix= $line" "$length" - tooenc "$line=" + recho "$line=" done - tooenc "$lsep" + recho "$lsep" } -function __eimportant() { tooenc "$(__edate)$(__eindent0)IMPORTANT! $(__eindent "$1" " ")"; } -function __eattention() { tooenc "$(__edate)$(__eindent0)ATTENTION! $(__eindent "$1" " ")"; } -function __eerror() { tooenc "$(__edate)$(__eindent0)ERROR: $(__eindent "$1" " ")"; } -function __ewarn() { tooenc "$(__edate)$(__eindent0)WARNING: $(__eindent "$1" " ")"; } -function __enote() { tooenc "$(__edate)$(__eindent0)NOTE: $(__eindent "$1" " ")"; } -function __einfo() { tooenc "$(__edate)$(__eindent0)INFO: $(__eindent "$1" " ")"; } -function __edebug() { tooenc "$(__edate)$(__eindent0)DEBUG: $(__eindent "$1" " ")"; } -function __eecho() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } -function __eecho_() { tooenc_ "$(__edate)$(__eindent0)$(__eindent "$1")"; } +function __eimportant() { recho "$(__edate)$(__eindent0)IMPORTANT! $(__eindent "$1" " ")"; } +function __eattention() { recho "$(__edate)$(__eindent0)ATTENTION! $(__eindent "$1" " ")"; } +function __eerror() { recho "$(__edate)$(__eindent0)ERROR: $(__eindent "$1" " ")"; } +function __ewarn() { recho "$(__edate)$(__eindent0)WARNING: $(__eindent "$1" " ")"; } +function __enote() { recho "$(__edate)$(__eindent0)NOTE: $(__eindent "$1" " ")"; } +function __einfo() { recho "$(__edate)$(__eindent0)INFO: $(__eindent "$1" " ")"; } +function __edebug() { recho "$(__edate)$(__eindent0)DEBUG: $(__eindent "$1" " ")"; } +function __eecho() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; } +function __eecho_() { recho_ "$(__edate)$(__eindent0)$(__eindent "$1")"; } -function __estep() { tooenc "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } -function __estepe() { tooenc "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } -function __estepw() { tooenc "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } -function __estepn() { tooenc "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } -function __estepi() { tooenc "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } -function __estep_() { tooenc_ "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } -function __estepe_() { tooenc_ "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } -function __estepw_() { tooenc_ "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } -function __estepn_() { tooenc_ "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } -function __estepi_() { tooenc_ "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } +function __estep() { recho "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } +function __estepe() { recho "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } +function __estepw() { recho "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } +function __estepn() { recho "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } +function __estepi() { recho "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } +function __estep_() { recho_ "$(__edate)$(__eindent0). $(__eindent "$1" " ")"; } +function __estepe_() { recho_ "$(__edate)$(__eindent0).E $(__eindent "$1" " ")"; } +function __estepw_() { recho_ "$(__edate)$(__eindent0).W $(__eindent "$1" " ")"; } +function __estepn_() { recho_ "$(__edate)$(__eindent0).N $(__eindent "$1" " ")"; } +function __estepi_() { recho_ "$(__edate)$(__eindent0).I $(__eindent "$1" " ")"; } -function __action() { tooenc "$(__edate)$(__eindent0)ACTION: $(__eindent "$1" " ")"; } -function __asuccess() { tooenc "$(__edate)$(__eindent0)(OK) $(__eindent "$1" " ")"; } -function __afailure() { tooenc "$(__edate)$(__eindent0)(KO) $(__eindent "$1" " ")"; } -function __adone() { tooenc "$(__edate)$(__eindent0)$(__eindent "$1")"; } +function __action() { recho "$(__edate)$(__eindent0)ACTION: $(__eindent "$1" " ")"; } +function __asuccess() { recho "$(__edate)$(__eindent0)(OK) $(__eindent "$1" " ")"; } +function __afailure() { recho "$(__edate)$(__eindent0)(KO) $(__eindent "$1" " ")"; } +function __adone() { recho "$(__edate)$(__eindent0)$(__eindent "$1")"; } diff --git a/bash/src/base.args.sh b/bash/src/base.args.sh index 393a7c5..43e63ae 100644 --- a/bash/src/base.args.sh +++ b/bash/src/base.args.sh @@ -124,8 +124,8 @@ optdesc commence par ++, c'est une option avancée qui n'est pas affichée par défaut." function parse_args() { eval "$NULIB__DISABLE_SET_X" + [ -n "$NULIB_ARGS_ONERROR_RETURN" ] && set_die_return local __r= - local __DIE='[ -n "$NULIB_ARGS_ONERROR_RETURN" ] && return 1 || die' if ! is_array args; then eerror "Invalid args definition: args must be defined" @@ -145,17 +145,33 @@ function parse_args() { __r=1 else __DEFS=("$@") - __parse_args || __r=1 + __nulib_args_parse_args || __r=1 fi eval "$NULIB__ENABLE_SET_X" if [ -n "$__r" ]; then - eval "$__DIE" + die || return 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 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 __popt __sopts __lopts local -a __defs @@ -165,10 +181,10 @@ function __parse_args() { +) __popt="$1"; shift; continue;; -) __popt="$1"; shift; continue;; -*) 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 # est-ce que l'option prend un argument? - local __def __witharg __valdesc + local __def __longdef __witharg __valdesc __witharg= for __def in "${__defs[@]}"; do if [ "${__def%::*}" != "$__def" ]; then @@ -180,23 +196,36 @@ function __parse_args() { # définitions __sopts et __lopts for __def in "${__defs[@]}"; do __def="${__def%%:*}" + __longdef= if [[ "$__def" == --* ]]; then # --longopt __def="${__def#--}" __lopts="$__lopts${__lopts:+,}$__def$__witharg" + __longdef=1 elif [[ "$__def" == -* ]] && [ ${#__def} -eq 2 ]; then # -o __def="${__def#-}" __sopts="$__sopts$__def$__witharg" - [ "$__def" == h ] && __AUTOH= - [ "$__def" == D ] && __AUTOD= + case "$__def" in + h) __AUTOH=;; + L) __NOAUTOL+=("-$__def");; + Q|q|v|D) __NOAUTOV+=("-$__def");; + b|y|i) __NOAUTOI+=("-$__def");; + esac else # -longopt ou longopt __def="${__def#-}" __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 - [ "$__def" == help -o "$__def" == help++ ] && __AUTOHELP= - [ "$__def" == debug ] && __AUTODEBUG= done # sauter l'action shift @@ -209,8 +238,12 @@ function __parse_args() { [ -n "$__AUTOH" ] && __sopts="${__sopts}h" [ -n "$__AUTOHELP" ] && __lopts="$__lopts${__lopts:+,}help,help++" - [ -n "$__AUTOD" ] && __sopts="${__sopts}D" - [ -n "$__AUTODEBUG" ] && __lopts="$__lopts${__lopts:+,}debug" + __nulib_args_add_sopt __NOAUTOL L + __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" local -a __getopt_args @@ -222,7 +255,7 @@ function __parse_args() { else # relancer pour avoir le message d'erreur LANG=C getopt "${__getopt_args[@]}" 2>&1 1>/dev/null - eval "$__DIE" + die || return fi ## puis traiter les options @@ -373,7 +406,7 @@ $prefix$usage" fi [[ "$1" == -* ]] || break option_="$1"; shift - __parse_opt "$option_" + __nulib_args_parse_opt "$option_" if [ -n "$__witharg" ]; then # l'option prend un argument value_="$1"; shift @@ -387,7 +420,7 @@ $prefix$usage" unset -f inc@ res@ add@ set@ showhelp@ args=("$@") } -function __parse_opt() { +function __nulib_args_parse_opt() { # $1 est l'option spécifiée local option_="$1" set -- "${__DEFS[@]}" @@ -460,27 +493,62 @@ function __parse_opt() { [ -n "$__found" ] && return 0 done - if [ -n "$__AUTOH" -a "$option_" == -h ]; then - __action="showhelp@" - return 0 - fi - if [ -n "$__AUTOHELP" ]; then - if [ "$option_" == --help ]; then - __action="showhelp@" - return 0 - elif [ "$option_" == --help++ ]; then - __action="showhelp@ ++" + case "$option_" in + -h) + if [ -n "$__AUTOH" ]; then + __action='showhelp@' return 0 fi - fi - if [ -n "$__AUTOD" -a "$option_" == -D ]; then - __action=set_debug - return 0 - fi - if [ -n "$__AUTODEBUG" -a "$option_" == --debug ]; then - __action=set_debug - return 0 - fi + ;; + --help) + if [ -n "$__AUTOHELP" ]; then + __action='showhelp@' + return 0 + fi + ;; + --help++) + if [ -n "$__AUTOHELP" ]; then + __action='showhelp@ ++' + return 0 + fi + ;; + -L) + if ! array_contains __NOAUTOL "$option_"; then + __action='elogto $value_' + return 0 + 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 - eerror "Unexpected option '$option_'"; eval "$__DIE" + die "Unexpected option '$option_'" || return } diff --git a/bash/src/base.input.sh b/bash/src/base.input.sh index 9e9acf0..c81fbc8 100644 --- a/bash/src/base.input.sh +++ b/bash/src/base.input.sh @@ -62,7 +62,7 @@ function ask_yesno() { else __eecho_ "Voulez-vous continuer?" 1>&2 fi - tooenc_ " $prompt " 1>&2 + echo_ " $prompt " 1>&2 uread r is_yes "${r:-$default}" else @@ -198,17 +198,17 @@ function __rv_read() { __eecho_ "Entrez la valeur" 1>&2 fi if [ -n "$__rv_readline" ]; then - tooenc_ ": " 1>&2 + echo_ ": " 1>&2 uread -e ${__rv_d:+-i"$__rv_d"} "${__rv_opts[@]}" __rv_r else if [ -n "$__rv_d" ]; then if [ -n "$__rv_showdef" ]; then - tooenc_ " [$__rv_d]" 1>&2 + echo_ " [$__rv_d]" 1>&2 else - tooenc_ " [****]" 1>&2 + echo_ " [****]" 1>&2 fi fi - tooenc_ ": " 1>&2 + echo_ ": " 1>&2 uread "${__rv_opts[@]}" __rv_r [ -n "$__rv_nl" ] && echo fi @@ -217,6 +217,7 @@ function __rv_read() { _setv "$__rv_v" "$__rv_r" return 0 fi + echo done } @@ -268,7 +269,7 @@ function simple_menu() { else __eecho_ "Entrez le numéro de l'option choisie" 1>&2 fi - tooenc_ ": " 1>&2 + echo_ ": " 1>&2 uread __sm_choice # Valeur par défaut @@ -291,7 +292,7 @@ function simple_menu() { let __sm_c=$__sm_c+1 if [ "$__sm_c" -eq 5 ]; then # sauter une ligne toutes les 4 tentatives - tooenc "" 1>&2 + echo 1>&2 __sm_c=0 fi done @@ -438,7 +439,7 @@ function __void_actions_menu() { if [ $c -eq 0 ]; then [ -n "$title" ] && __etitle "$title" 1>&2 __eecho_ "=== Actions disponibles: " 1>&2 - tooenc "$action_title" 1>&2 + recho "$action_title" 1>&2 fi if [ -n "$actyc" ]; then __eecho_ "$actyc" 1>&2 @@ -447,7 +448,7 @@ function __void_actions_menu() { else __eecho_ "Entrez l'action à effectuer" 1>&2 fi - tooenc_ ": " 1>&2 + echo_ ": " 1>&2 uread choice if [ -z "$choice" -a -n "$default_action" ]; then select_action="$default_action" @@ -468,7 +469,7 @@ function __void_actions_menu() { let c=$c+1 if [ $c -eq 5 ]; then # sauter une ligne toutes les 4 tentatives - tooenc "" 1>&2 + echo 1>&2 c=0 fi done @@ -484,21 +485,21 @@ function __options_actions_menu() { i=1 for option in "${options[@]}"; do if [ "$option" == "$select_option" ]; then - tooenc "$i*- $option" 1>&2 + echo "$i*- $option" 1>&2 else - tooenc "$i - $option" 1>&2 + echo "$i - $option" 1>&2 fi let i=$i+1 done __estepn_ "Actions disponibles: " 1>&2 - tooenc "$action_title" 1>&2 + recho "$action_title" 1>&2 fi if [ -n "$optyc" ]; then __eecho_ "$optyc" 1>&2 else __eecho_ "Entrez l'action et le numéro de l'option choisie" 1>&2 fi - tooenc_ ": " 1>&2 + echo_ ": " 1>&2 uread choice # vérifier la saisie @@ -572,7 +573,7 @@ function __options_actions_menu() { let c=$c+1 if [ $c -eq 5 ]; then # sauter une ligne toutes les 4 tentatives - tooenc "" 1>&2 + echo "" 1>&2 c=0 fi done diff --git a/bash/src/base.output.sh b/bash/src/base.output.sh index ae51afd..15f2040 100644 --- a/bash/src/base.output.sh +++ b/bash/src/base.output.sh @@ -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 # qui vaut par défaut $NULIB_OUTPUT_ENCODING local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}" @@ -93,9 +93,8 @@ function tooenc() { iconv -f -utf-8 -t "$to" <<<"$value" fi } -function uecho() { tooenc "$*"; } -function tooenc_() { +function uecho_() { # $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 local value="$1" to="${2:-$NULIB_OUTPUT_ENCODING}" @@ -105,7 +104,6 @@ function tooenc_() { recho_ "$value" | iconv -f utf-8 -t "$to" fi } -function uecho_() { tooenc_ "$*"; } export NULIB_QUIETLOG export NULIB__TMPLOG @@ -210,7 +208,7 @@ function __eindent() { # indenter les lignes de $1, sauf la première local -a lines; local line first=1 local indent="$(__eindent0)$2" - setx -a lines=echo "$1" + setx -a lines=recho "$1" for line in "${lines[@]}"; do if [ -n "$first" ]; then recho "$line" @@ -232,7 +230,11 @@ function __complete() { } PRETTYOPTS=() -function set_verbosity() { :;} +function set_verbosity() { + case "$1" in + -D|--debug) NULIB_DEBUG=1;; + esac +} function check_verbosity() { return 0; } function get_verbosity_option() { :;} diff --git a/bash/src/pman.sh b/bash/src/pman.sh index dcd9dfb..f2f5d3d 100644 --- a/bash/src/pman.sh +++ b/bash/src/pman.sh @@ -159,6 +159,7 @@ function load_branches() { local what="${1:-all}"; shift case "$what" in all) + [ -n "$Origin" ] || Origin=origin setx CurrentBranch=git_get_branch setx -a LocalBranches=git_list_branches setx -a RemoteBranches=git_list_rbranches "$Origin" @@ -195,12 +196,12 @@ function load_branches() { ReleaseBranch= HotfixBranch= MainBranch= - Dist=Branch - for branch in "${AllBranches[@]}"; do + DistBranch= + for branch in "${LocalBranches[@]}"; do if [ "$branch" == "$UPSTREAM" ]; then UpstreamBranch="$branch" elif [[ "$branch" == "$FEATURE"* ]]; then - FeatureBranch+=("$branch") + FeatureBranches+=("$branch") elif [ "$branch" == "$DEVELOP" ]; then DevelopBranch="$branch" elif [[ "$branch" == "$RELEASE"* ]]; then @@ -224,13 +225,15 @@ function load_config() { if [ -n "$ConfigFile" ]; then source "$ConfigFile" || die || return elif [ -n "$ConfigBranch" ]; then + # c'est le seul cas où ConfigFile reste vide if ! array_contains LocalBranches "$ConfigBranch"; then die "$ConfigBranch: branche de configuration introuvable" || return else - ac_set_tmpfile ConfigFile - git show "$ConfigBranch:.pman.conf" >"$ConfigFile" 2>/dev/null - [ -s "$ConfigFile" ] || die "$ConfigBranch: aucune configuration trouvée sur cette branche" || return - source "$ConfigFile" + local config + ac_set_tmpfile config + git show "$ConfigBranch:.pman.conf" >"$config" 2>/dev/null + [ -s "$config" ] || die "$ConfigBranch: aucune configuration trouvée sur cette branche" || return + source "$config" fi elif [ -f .pman.conf ]; then ConfigFile="$(pwd)/.pman.conf" @@ -250,6 +253,16 @@ function load_config() { ################################################################################ # 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() { [ ${#push_branches[*]} -gt 0 ] || return [ -n "$Origin" ] || Origin=origin diff --git a/bash/src/pretty.sh b/bash/src/pretty.sh index 2d4f32c..de252fc 100644 --- a/bash/src/pretty.sh +++ b/bash/src/pretty.sh @@ -108,11 +108,17 @@ function set_interaction() { # set_interaction en fonction des arguments de la ligne de commande. A utiliser # de cette manière: # 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é" +) +VERBOSITYOPTS=( -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" ) +PRETTYOPTS=("${LOGTOOPTS[@]}" "${VERBOSITYOPTS[@]}" "${INTERACTIONOPTS[@]}") function show_error() { [ "$__verbosity" -ge 1 ]; } function show_warn() { [ "$__verbosity" -ge 2 ]; } diff --git a/bash/tests/test-interaction.sh b/bash/tests/test-interaction.sh new file mode 100755 index 0000000..db35861 --- /dev/null +++ b/bash/tests/test-interaction.sh @@ -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" diff --git a/bash/tests/test-output.sh b/bash/tests/test-output.sh index 56a5812..3b369d7 100755 --- a/bash/tests/test-output.sh +++ b/bash/tests/test-output.sh @@ -7,7 +7,6 @@ Multiline= Banner= args=( "afficher divers messages avec les fonctions e*" - -D,--debug '$set_debug' -d,--date NULIB_ELOG_DATE=1 -m,--myname NULIB_ELOG_MYNAME=1 -n,--nc,--no-color '$__set_no_colors 1' diff --git a/bash/tests/test-verbosity.sh b/bash/tests/test-verbosity.sh new file mode 100755 index 0000000..4b53d8f --- /dev/null +++ b/bash/tests/test-verbosity.sh @@ -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)" diff --git a/bin/_merge82 b/bin/_merge82 index 3c89e35..8a4c2bc 100755 --- a/bin/_merge82 +++ b/bin/_merge82 @@ -1,4 +1,4 @@ #!/bin/bash # -*- 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" "$@" diff --git a/bin/_pman-composer_local_deps.php b/bin/_pman-composer_local_deps.php new file mode 100755 index 0000000..badae7b --- /dev/null +++ b/bin/_pman-composer_local_deps.php @@ -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"; +} \ No newline at end of file diff --git a/bin/p b/bin/p index 561d88a..aedfdfc 100755 --- a/bin/p +++ b/bin/p @@ -20,8 +20,18 @@ function git_status() { fi } +function git_statuses() { + local cwd="$(pwd)" dir + for dir in "$@"; do + cd "$dir" || die + git_status --porcelain + cd "$cwd" + done +} + chdir= all= +composer= args=( "afficher l'état du dépôt" "[-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" -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" + -r,--composer composer=1 "faire l'opération sur tous les projets composer dépendants" ) parse_args "$@"; set -- "${args[@]}" @@ -50,16 +61,23 @@ if [ -n "$all" ]; then dirs+=("${dir%/.git}") done fi - setx cwd=pwd - for dir in "${dirs[@]}"; do - cd "$dir" || die - git_status --porcelain - cd "$cwd" - done + git_statuses "${dirs[@]}" + +elif [ -n "$composer" ]; then + # projets dépendants + git_ensure_gitvcs + 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 # répertoire courant uniquement - setx toplevel=git_get_toplevel - [ -n "$toplevel" ] && Cwd="$toplevel" + git_ensure_gitvcs + Cwd="$(git_get_toplevel)" args=() isatty || args+=(--porcelain) diff --git a/bin/pdev b/bin/pdev index 6a2f5d1..03e827c 100755 --- a/bin/pdev +++ b/bin/pdev @@ -25,6 +25,9 @@ function ensure_branches() { } 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 "\ Ce script va - 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 -a push_branches delete_branches - local after + local hook local comment= local or_die=" || exit 1" @@ -44,17 +47,22 @@ Ce script va if [ -n "\$merge" ]; then esection "Fusionner la branche" EOF - _mscript_merge_branch - after="AFTER_MERGE_${SrcType^^}"; [ -n "${!after}" ] && _scripta <<EOF + hook="BEFORE_MERGE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF ( -${!after} +${!hook} +)$or_die +EOF + _mscript_merge_branch + hook="AFTER_MERGE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF +( +${!hook} )$or_die EOF _scripta <<EOF fi EOF - if [ -z "$ForbidDelete" ]; then + if [ -n "$ShouldDelete" ]; then _scripta <<EOF ################################################################################ # delete @@ -62,9 +70,9 @@ if [ -n "\$delete" ]; then esection "Supprimer la branche" EOF _mscript_delete_branch - after="AFTER_DELETE_${SrcType^^}"; [ -n "${!after}" ] && _scripta <<EOF + hook="AFTER_DELETE_${SrcType^^}"; [ -n "${!hook}" ] && _scripta <<EOF ( -${!after} +${!hook} )$or_die EOF _scripta <<EOF @@ -77,6 +85,11 @@ EOF # push if [ -n "\$push" ]; then esection "Pousser les branches" +EOF + hook="BEFORE_PUSH_${DestType^^}"; [ -n "${!hook}" ] && _scripta <<EOF +( +${!hook} +)$or_die EOF _script_push_branches if [ ${#delete_branches[*]} -gt 0 ]; then @@ -85,35 +98,42 @@ EOF _script_push_branches _scripta <<<fi fi - after="AFTER_PUSH_${DestType^^}"; [ -n "${!after}" ] && _scripta <<EOF + hook="AFTER_PUSH_${DestType^^}"; [ -n "${!hook}" ] && _scripta <<EOF ( -${!after} +${!hook} )$or_die EOF _scripta <<EOF fi EOF - [ -n "$Delete" -o "$ForbidDelete" ] && Deleted=1 || Deleted= - [ -n "$Push" -o "$CantPush" ] && Pushed=1 || Pushed= - if [ -n "$_NoRunScript" ]; then - einfo "Veuillez consulter le script $script pour le détail des opérations à effectuer" + [ -n "$Delete" -o -z "$ShouldDelete" ] && Deleted=1 || Deleted= + [ -n "$ShouldDelete" -a -n "$Delete" ] && ShouldDelete= + [ -n "$ShouldPush" -a -n "$Push" ] && ShouldPush= + if [ -n "$_Fake" ]; then + cat "$script" elif ! "$script" merge ${Delete:+delete} ${Push:+push}; then eimportant "\ 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 - elif [ -n "$Deleted" -a -n "$Pushed" ]; then + elif [ -n "$Deleted" -a -n "$Push" ]; then [ -n "$_KeepScript" ] || rm "$script" + [ -n "$AfterMerge" ] && eval "$AfterMerge" else - local cmd - [ -n "$Deleted" ] || cmd="$cmd - ./$script delete" - [ -n "$Pushed" ] || cmd="$cmd - ./$script push" - einfo "\ + local msg="\ 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 } @@ -125,24 +145,27 @@ chdir= Origin= ConfigBranch= ConfigFile= +_Fake= _KeepScript= -_NoRunScript= action=merge TechMerge= SquashMsg= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= [ -z "$PMAN_NO_DELETE" ] && Delete=1 || Delete= +AfterMerge= args=( "fusionner la branche source dans la branche destination correspondante" " [source] CONFIGURATION -Le fichier .pman.conf contient la configuration des branches.Les variables +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> -xxxType valant UPSTREAM, DEVELOP, FEATURE, RELEASE, MAIN, HOTFIX, DIST" +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" -O:,--origin Origin= "++\ origine à partir de laquelle les branches distantes sont considérées" @@ -151,8 +174,8 @@ 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" + --fake _Fake=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 "\ lister les modifications qui seraient fusionnées dans la branche destination" -b,--rebase action=rebase "\ @@ -175,6 +198,10 @@ ne pas supprimer la branche après la fusion dans la destination" --delete Delete=1 "++\ supprimer la branche après la fusion dans la destination. 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[@]}" @@ -184,13 +211,7 @@ load_branches all load_config "$MYNAME" load_branches current "$1" -CantPush= -[ -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= +resolve_should_push quiet # puis faire l'action que l'on nous demande case "$action" in @@ -200,24 +221,26 @@ show) show_action "$@" ;; merge) - ForbidDelete= - case "$SrcType" in - develop|release|hotfix) - die "$SrcBranch: cette branche doit être fusionnée dans $DestBranch avec prel" - ;; - *) - # n'autoriser la suppression que pour feature - [ "$SrcType" == feature ] || ForbidDelete=1 - ;; - esac - [ -n "$ForbidDelete" ] && Delete= - 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 + ShouldDelete=1 + no_merge_msg="$SrcBranch: cette branche doit être fusionnée dans $DestBranch avec prel" + if [ "$SrcType" == develop ]; then + [ -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 + [ "$SrcType" == feature ] || ShouldDelete= + [ -z "$ShouldDelete" ] && Delete= + [ -z "$_Fake" ] && git_ensure_cleancheckout + if array_contains LocalBranches "$SrcBranch"; then ensure_branches 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 ;; *) diff --git a/bin/pman b/bin/pman index 2c999e4..d4b91a9 100755 --- a/bin/pman +++ b/bin/pman @@ -59,9 +59,9 @@ function _init_config() { } function init_repo_action() { - [ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé" + local -a push_branches; local config - local -a push_branches + [ ${#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" @@ -78,9 +78,11 @@ function init_repo_action() { } function init_config_action() { - [ -f .pman.conf ] && die "La configuration pman a déjà été initialisée" + local -a push_branches; config - local -a push_branches + [ -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" @@ -89,17 +91,41 @@ function init_config_action() { _push_branches } +function _ensure_main_branch() { + [ -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é?)" +} + +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 - [ -n "$DEVELOP" ] || die "La branche DEVELOP 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é?)" + 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}" ask_yesno "Voulez-vous continuer?" O || die - local -a push_branches - einfo "Création de la branche $DEVELOP" git checkout -b "$DEVELOP" "$MAIN" || die push_branches+=("$DEVELOP") @@ -109,17 +135,26 @@ function init_develop_action() { git checkout -q "$DEVELOP" } +function _ensure_upstream_branch() { + [ -n "$UPSTREAM" ] || die "La branche UPSTREAM n'a pas été définie" + [ -n "$UpstreamBranch" ] || die "$UPSTREAM: 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 - [ -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 "$DevelopBranch" ] || die "$DEVELOP: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" + 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}" ask_yesno "Voulez-vous continuer?" O || die - local -a push_branches; local config - # faire une copie de la configuration actuelle ac_set_tmpfile config cp "$ConfigFile" "$config" @@ -145,17 +180,26 @@ function init_upstream_action() { git checkout -q "$UPSTREAM" } +function _ensure_dist_branch() { + [ -n "$DIST" ] || die "La branche DIST n'a pas été définie" + [ -n "$DistBranch" ] || die "$DIST: 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 - [ -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 "$MainBranch" ] || die "$MAIN: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" + 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}" ask_yesno "Voulez-vous continuer?" O || die - local -a push_branches - einfo "Création de la branche $DIST" git checkout -b "$DIST" "$MAIN" || die push_branches+=("$DIST") @@ -166,18 +210,24 @@ function init_dist_action() { } function init_feature_action() { - local branch="${1#$FEATURE}" - [ -n "$branch" ] || die "Vous devez définir la nom de la branche à créer" + local -a push_branches; local branch + + [ -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" - if ! array_contains AllBranches "$branch"; then - [ -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é?)" + + if ! array_contains LocalBranches "$branch"; then + 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}" ask_yesno "Voulez-vous continuer?" O || die - local -a push_branches - einfo "Création de la branche $branch" git checkout -b "$branch" "$DEVELOP" || die push_branches+=("$branch") @@ -192,7 +242,7 @@ function init_action() { case "$what" in init|repo|r) init_repo_action "$@";; config) init_config_action "$@";; - main|m) git checkout -q "$MAIN";; + main|m) checkout_main_action;; develop|dev|d) init_develop_action "$@";; upstream|up|u) init_upstream_action "$@";; dist|x) init_dist_action "$@";; @@ -209,7 +259,7 @@ ConfigBranch= ConfigFile= action=init Origin= -Push=1 +[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= ForceCreate= args=( "gérer un projet git" diff --git a/bin/prel b/bin/prel index 30a0706..e1af6eb 100755 --- a/bin/prel +++ b/bin/prel @@ -44,6 +44,8 @@ function create_release_action() { [ -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 Version="$(<VERSION.txt)" @@ -83,6 +85,11 @@ Vous devrez: # create if [ -n "\$create" ]; then esection "Création de la release" +EOF + [ -n "$BEFORE_CREATE_RELEASE" ] && _scripta <<EOF +( +$BEFORE_CREATE_RELEASE +)$or_die EOF _rscript_create_release_branch [ -n "$AFTER_CREATE_RELEASE" ] && _scripta <<EOF @@ -99,6 +106,11 @@ EOF # merge if [ -n "\$merge" ]; then esection "Fusionner la release" +EOF + [ -n "$BEFORE_MERGE_RELEASE" ] && _scripta <<EOF +( +$BEFORE_MERGE_RELEASE +)$or_die EOF _rscript_merge_release_branch "$DestBranch" "$Tag" _rscript_merge_release_branch "$SrcBranch" @@ -117,6 +129,11 @@ EOF # push if [ -n "\$push" ]; then esection "Pousser branches et tags" +EOF + [ -n "$BEFORE_PUSH_RELEASE" ] && _scripta <<EOF +( +$BEFORE_PUSH_RELEASE +)$or_die EOF _script_push_branches _script_push_tags @@ -129,26 +146,25 @@ EOF fi EOF - [ -n "$Merge" ] && Merged=1 || Merged= - [ -n "$Push" -o "$CantPush" ] && Pushed=1 || Pushed= - if [ -n "$_NoRunScript" ]; then - einfo "Veuillez consulter le script $script pour le détail des opérations à effectuer" + [ -z "$ManualRelease" -a -n "$Merge" ] && ShouldMerge= || ShouldMerge=1 + [ -n "$ShouldPush" -a -n "$Push" ] && ShouldPush= + if [ -n "$_Fake" ]; then + cat "$script" elif ! "$script" create ${Merge:+merge} ${Push:+push}; then eimportant "\ 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 - elif [ -n "$Merged" -a -n "$Pushed" ]; then + elif [ -n "$Merge" -a -n "$Push" ]; then [ -n "$_KeepScript" ] || rm "$script" else - local cmd - [ -n "$Merged" ] || cmd="$cmd - ./$script merge" - [ -n "$Pushed" ] || cmd="$cmd - ./$script push" einfo "\ 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 } @@ -175,8 +191,8 @@ chdir= Origin= ConfigBranch= ConfigFile= +_Fake= _KeepScript= -_NoRunScript= action=release [ -z "$PMAN_NO_MERGE" ] && Merge=1 || Merge= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= @@ -188,11 +204,13 @@ args=( " -v VERSION [source] CONFIGURATION -Le fichier .pman.conf contient la configuration des branches - -Les variables supplémentaires suivantes peuvent être définies: +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" -O:,--origin Origin= "++\ @@ -202,8 +220,8 @@ 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" + --fake _Fake=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 "\ lister les modifications qui seraient intégrées dans la release" --release action=release "++\ @@ -223,7 +241,7 @@ c'est l'option par défaut" spécifier la version de la release à créer" -C,--current-version CurrentVersion=1 "++\ 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à" ) parse_args "$@"; set -- "${args[@]}" @@ -238,13 +256,7 @@ load_branches current "$1"; shift [ -n "$ManualRelease" ] && Merge= [ -z "$Merge" ] && Push= -CantPush= -[ -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= +resolve_should_push quiet # puis faire l'action que l'on nous demande case "$action" in @@ -254,7 +266,7 @@ show) show_action "$@" ;; release) - git_ensure_cleancheckout + [ -z "$_Fake" ] && git_ensure_cleancheckout ensure_branches case "$SrcType" in release) merge_release_action "$@";; diff --git a/bin/pwip b/bin/pwip new file mode 100755 index 0000000..787676b --- /dev/null +++ b/bin/pwip @@ -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 diff --git a/dockerfiles/Dockerfile.php-apache b/dockerfiles/Dockerfile.php-apache index 2a9e467..641de40 100644 --- a/dockerfiles/Dockerfile.php-apache +++ b/dockerfiles/Dockerfile.php-apache @@ -25,7 +25,7 @@ COPY --from=builder /src/su-exec/su-exec /g/ RUN /g/build 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 ENTRYPOINT ["/g/entrypoint"] diff --git a/dockerfiles/Dockerfile.php-apache+ic b/dockerfiles/Dockerfile.php-apache+ic index cfbbd61..8907e78 100644 --- a/dockerfiles/Dockerfile.php-apache+ic +++ b/dockerfiles/Dockerfile.php-apache+ic @@ -34,7 +34,7 @@ COPY --from=legacytools /g/ /g/ RUN /g/build nutools 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=builder /opt/oracle/ /opt/oracle/ diff --git a/php/src/cl.php b/php/src/cl.php index 8bb3b37..2397fe9 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -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 * $mappings qui contient des associations de la forme [$from => $to] diff --git a/php/src/ref/schema/ref_schema.php b/php/src/ref/schema/ref_schema.php index 9cfa10b..cee4786 100644 --- a/php/src/ref/schema/ref_schema.php +++ b/php/src/ref/schema/ref_schema.php @@ -6,7 +6,7 @@ class ref_schema { const NATURE_METASCHEMA = [ "nature" => ["string", null, "nature du schéma", "pkey" => 0, - "allowed_values" => ["assoc", "list", "scalar"], + "allowed_values" => ["scalar", "assoc", "list"], ], "title" => ["?string", null, "libellé de la valeur"], "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"], "formatter_func" => ["?callable", null, "fonction qui formatte la valeur pour affichage"], "format" => [null, null, "format à utiliser pour l'affichage"], - "" => ["array", "scalar", "nature du schéma", - "" => ["assoc", "schema" => self::NATURE_METASCHEMA], + "" => ["array", ["scalar"], "nature du schéma", + "schema" => self::NATURE_METASCHEMA, ], + "schema" => ["?array", null, "schéma de la valeur si c'est un array"], "name" => ["?string", null, "identifiant de la valeur"], "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"], diff --git a/php/src/ref/schema/ref_types.php b/php/src/ref/schema/ref_types.php index 24973d5..d7ce1d4 100644 --- a/php/src/ref/schema/ref_types.php +++ b/php/src/ref/schema/ref_types.php @@ -6,5 +6,6 @@ class ref_types { "boolean" => "bool", "integer" => "int", "flt" => "float", "double" => "float", "dbl" => "float", + "func" => "callable", "function" => "callable", ]; } diff --git a/php/src/tools/pman/ComposerFile.php b/php/src/tools/pman/ComposerFile.php index 5a48a1c..d85a957 100644 --- a/php/src/tools/pman/ComposerFile.php +++ b/php/src/tools/pman/ComposerFile.php @@ -138,6 +138,28 @@ class ComposerFile { } } + 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"; diff --git a/php/tests/clTest.php b/php/tests/clTest.php new file mode 100644 index 0000000..d2b834f --- /dev/null +++ b/php/tests/clTest.php @@ -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], []); + } +} diff --git a/php/tests/php/access/KeyAccessTest.php b/php/tests/php/access/KeyAccessTest.php deleted file mode 100644 index dc5bd4c..0000000 --- a/php/tests/php/access/KeyAccessTest.php +++ /dev/null @@ -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)); - } -} diff --git a/php/tests/php/access/ValueAccessTest.php b/php/tests/php/access/ValueAccessTest.php deleted file mode 100644 index a7d08c9..0000000 --- a/php/tests/php/access/ValueAccessTest.php +++ /dev/null @@ -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)); - } -} diff --git a/php/tests/php/content/cTest.php b/php/tests/php/content/cTest.php deleted file mode 100644 index 2f31b4a..0000000 --- a/php/tests/php/content/cTest.php +++ /dev/null @@ -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<q/>", 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 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( - "<h1>title<q/></h1><p>hello<nq/><span>brave<q/></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)); - } -} - diff --git a/php/tests/php/content/impl/AContent.php b/php/tests/php/content/impl/AContent.php deleted file mode 100644 index c53c376..0000000 --- a/php/tests/php/content/impl/AContent.php +++ /dev/null @@ -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>"]; - } -} diff --git a/php/tests/php/content/impl/APrintable.php b/php/tests/php/content/impl/APrintable.php deleted file mode 100644 index 7a75c2f..0000000 --- a/php/tests/php/content/impl/APrintable.php +++ /dev/null @@ -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>"; - } -} diff --git a/php/tests/php/content/impl/ATag.php b/php/tests/php/content/impl/ATag.php deleted file mode 100644 index b4cc2ed..0000000 --- a/php/tests/php/content/impl/ATag.php +++ /dev/null @@ -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>", - ]; - } -} diff --git a/php/tests/php/content/impl/html.php b/php/tests/php/content/impl/html.php deleted file mode 100644 index 3567b2e..0000000 --- a/php/tests/php/content/impl/html.php +++ /dev/null @@ -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); } -} diff --git a/php/tests/schema/_scalar/ScalarSchemaTest.php b/php/tests/schema/_scalar/ScalarSchemaTest.php deleted file mode 100644 index e004168..0000000 --- a/php/tests/schema/_scalar/ScalarSchemaTest.php +++ /dev/null @@ -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")); - } -} diff --git a/php/tests/schema/types/boolTest.php b/php/tests/schema/types/boolTest.php deleted file mode 100644 index 8f990e3..0000000 --- a/php/tests/schema/types/boolTest.php +++ /dev/null @@ -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); - } -} diff --git a/php/tests/schema/types/floatTest.php b/php/tests/schema/types/floatTest.php deleted file mode 100644 index 193d407..0000000 --- a/php/tests/schema/types/floatTest.php +++ /dev/null @@ -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); - } -} diff --git a/php/tests/schema/types/intTest.php b/php/tests/schema/types/intTest.php deleted file mode 100644 index 29de7ce..0000000 --- a/php/tests/schema/types/intTest.php +++ /dev/null @@ -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); - } -} diff --git a/php/tests/schema/types/strTest.php b/php/tests/schema/types/strTest.php deleted file mode 100644 index 45eda17..0000000 --- a/php/tests/schema/types/strTest.php +++ /dev/null @@ -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); - } -} diff --git a/php/tests/schema/types/unionTest.php b/php/tests/schema/types/unionTest.php deleted file mode 100644 index c208087..0000000 --- a/php/tests/schema/types/unionTest.php +++ /dev/null @@ -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); - } -} diff --git a/runphp/runphp b/runphp/runphp index 1a03b5f..4bfe2ed 100755 --- a/runphp/runphp +++ b/runphp/runphp @@ -455,15 +455,18 @@ OPTIONS function host_docker_run() { # lancer une commande avec docker - SOPTS=+w: - LOPTS=help,chdir:,no-use-rslave - args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" + if [ "$1" == composer ]; then + : # pas d'analyse d'argument pour composer + else + SOPTS=+w: + LOPTS=help,chdir:,no-use-rslave + args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" - while [ $# -gt 0 ]; do - case "$1" in - --) shift; break;; - --help) - eecho "\ + while [ $# -gt 0 ]; do + case "$1" in + --) shift; break;; + --help) + eecho "\ runphp: lancer une commande dans un environnement PHP déterminé USAGE @@ -490,14 +493,15 @@ OPTIONS aller dans le répertoire spécifié avant de lancer la commande --no-use-rslave paramètre montage des volumes" - exit 0 - ;; - -w|--chdir) shift; Chdir="$1";; - --no-use-rslave) UseRslave=;; - *) die "$1: option non configurée";; - esac - shift - done + exit 0 + ;; + -w|--chdir) shift; Chdir="$1";; + --no-use-rslave) UseRslave=;; + *) die "$1: option non configurée";; + esac + shift + done + fi args=( run -it --rm @@ -573,20 +577,24 @@ function container_exec() { fi fi - SOPTS=+w: - LOPTS=chdir: - args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" + if [ "$1" == composer ]; then + : # pas d'analyse d'argument pour composer + else + SOPTS=+w: + LOPTS=chdir: + args="$(getopt -n "$MYNAME" -o "$SOPTS" -l "$LOPTS" -- "$@")" || exit 1; eval "set -- $args" - chdir= - action= - while [ $# -gt 0 ]; do - case "$1" in - --) shift; break;; - -w|--chdir) shift; chdir="$1";; - *) die "$1: option non configurée";; - esac - shift - done + chdir= + action= + while [ $# -gt 0 ]; do + case "$1" in + --) shift; break;; + -w|--chdir) shift; chdir="$1";; + *) die "$1: option non configurée";; + esac + shift + done + fi if [ $# -eq 0 ]; then die "no command specified"