From 1671354fd8eed5044d3f7593f3db9185f4c16bc6 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 04:33:36 +0400 Subject: [PATCH 01/23] Init changelog & version 0.5.0p82 --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index b4fd91d..1f6a6e8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,5 @@ +## Release 0.5.0p82 du 30/04/2025-04:33 + ## Release 0.5.0p74 du 30/04/2025-04:31 * `3ee92ef` ajout str::replace From d70612261dfc9e33e46dd9257aaedc79d2f036ad Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 05:00:23 +0400 Subject: [PATCH 02/23] ajout infos release --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..3affeb9 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# nulib + + +## Release + +Exemple: release de la version 0.6.0 +~~~sh +version=0.6.0 + +# release sur la branche dev74 +prel -v$version + +# fusionner dans dev82 +_merge82 + +# release sur la branche dev82 +git checkout dev82 +prel -C + +# récupérer le commit de maj du changelog +commit="$(git log --grep="Init changelog . version ${version}p82" --format=%H)" +git checkout dev74 +git cherry-pick "$commit" +pp -a +~~~ + +-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file From a371a68ee2d388d6970eec8ccf83b51cbc8e4e37 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 05:31:32 +0400 Subject: [PATCH 03/23] maj doc --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3affeb9..eee5634 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,18 @@ Exemple: release de la version 0.6.0 ~~~sh version=0.6.0 -# release sur la branche dev74 +## branche dev74 +git checkout dev74 + prel -v$version -# fusionner dans dev82 _merge82 -# release sur la branche dev82 +## branche dev82 git checkout dev82 + prel -C -# récupérer le commit de maj du changelog commit="$(git log --grep="Init changelog . version ${version}p82" --format=%H)" git checkout dev74 git cherry-pick "$commit" From aabdb3f76566419eed8702749897a6d07388a169 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 06:51:49 +0400 Subject: [PATCH 04/23] cosmetic --- php/src/db/CapacitorStorage.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/src/db/CapacitorStorage.php b/php/src/db/CapacitorStorage.php index e7ff6af..ba00c07 100644 --- a/php/src/db/CapacitorStorage.php +++ b/php/src/db/CapacitorStorage.php @@ -677,7 +677,7 @@ abstract class CapacitorStorage { function _delete(CapacitorChannel $channel, $filter, $func, ?array $args): int { $this->_create($channel); if ($func === null) $func = CapacitorChannel::onDelete; - $onEach = func::with($func)->bind($channel); + $onDelete = func::with($func)->bind($channel); $db = $this->db(); # si on est déjà dans une transaction, désactiver la gestion des transactions $manageTransactions = $channel->isManageTransactions() && !$db->inTransaction(); @@ -693,8 +693,8 @@ abstract class CapacitorStorage { $all = $this->_allCached("delete", $channel, $filter); foreach ($all as $values) { $rowIds = $this->getRowIds($channel, $values); - $delete = boolval($onEach->invoke([$values["item"], $values, ...$args])); - if ($delete) { + $shouldDelete = boolval($onDelete->invoke([$values["item"], $values, ...$args])); + if ($shouldDelete) { $db->exec([ "delete", "from" => $tableName, From 87e262cfe2a57e732ae41788beae9264e3e76a9e Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 08:23:06 +0400 Subject: [PATCH 05/23] ajout cl::delv --- php/src/cl.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/php/src/cl.php b/php/src/cl.php index 4978afe..a1073ee 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -302,6 +302,27 @@ class cl { } } + /** + * si $array est un array ou une instance de ArrayAccess&Traversable, + * supprimer le premier élément dont la valeur est $value + * + * @param array|ArrayAccess $array + */ + static final function delv(&$array, $value, bool $strict=false): void { + if (is_array($array)) { + $key = array_search($value, $array, $strict); + if ($key !== false) unset($array[$key]); + } elseif ($array instanceof ArrayAccess && $array instanceof Traversable) { + $found = false; + foreach ($array as $key => $val) { + if ($strict) $found = $val === $value; + else $found = $val == $value; + if ($found) break; + } + if ($found) $array->offsetUnset($key); + } + } + /** retourner le nombre d'éléments de $array */ static final function count(?array $array): int { return $array !== null? count($array): 0; From aef0533d9b1aec077255f78a037e873d2e2e5e6a Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 13:59:18 +0400 Subject: [PATCH 06/23] ajout str::split --- php/src/str.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/php/src/str.php b/php/src/str.php index 347726b..2dc71ba 100644 --- a/php/src/str.php +++ b/php/src/str.php @@ -328,6 +328,22 @@ class str { else return preg_split('/\s+/', $s); } + /** + * découper la chaine: + * - avec preg_split si $sep est une expression régulière /re/ + * - avec explode sinon + */ + static final function split(string $sep, ?string $s): ?array { + if ($s === null) return null; + if ($sep === "") { + return [$s]; + } elseif (substr($sep, 0, 1) === "/") { + return preg_split($sep, $s); + } else { + return explode($sep, $s); + } + } + /** * joindre les éléments de $parts comme avec implode(), mais en ignorant les * valeurs fausses (cela n'inclue pas la chaine "0") From 24ecb913dc3f7a74400a2b18ad87887db98b09ad Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 16:02:10 +0400 Subject: [PATCH 07/23] modifs.mineures sans commentaires --- php/src/php/func.php | 37 +++++++++++++++++++++++++------------ php/tests/php/funcTest.php | 12 ++++++------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/php/src/php/func.php b/php/src/php/func.php index 675d359..f2d2883 100644 --- a/php/src/php/func.php +++ b/php/src/php/func.php @@ -59,9 +59,10 @@ class func { * @param bool $strict vérifier l'inexistence de la classe et l'existence de * la fonction (ne pas uniquement faire une vérification syntaxique) */ - static function verifix_function(&$func, bool $strict=true, ?string &$reason=null): bool { + static function verifix_function(&$func, ?array &$args=null, bool $strict=true, ?string &$reason=null): bool { if ($strict) $reason = null; if ($func instanceof ReflectionFunction) return true; + $rargs = null; if (is_string($func)) { $c = false; $f = $func; @@ -70,6 +71,7 @@ class func { $c = $func[0]; if (!array_key_exists(1, $func)) return false; $f = $func[1]; + $rargs = array_slice($func, 2); } else { return false; } @@ -90,6 +92,7 @@ class func { } } $func = [false, $f]; + if ($rargs) $args = cl::merge($rargs, $args); return true; } @@ -98,7 +101,7 @@ class func { * {@link self::verifix_function()} */ static function is_function($func, bool $strict=true, ?string &$reason=null): bool { - return self::verifix_function($func, $strict, $reason); + return self::verifix_function($func, $args, $strict, $reason); } ############################################################################# @@ -115,9 +118,10 @@ class func { * @param bool $strict vérifier l'existence de la classe (ne pas uniquement * faire une vérification syntaxique) */ - static function verifix_class(&$func, bool $strict=true, ?string &$reason=null): bool { + static function verifix_class(&$func, ?array &$args=null, bool $strict=true, ?string &$reason=null): bool { if ($strict) $reason = null; if ($func instanceof ReflectionClass) return true; + $rargs = null; if (is_string($func)) { $c = $func; $f = false; @@ -126,6 +130,7 @@ class func { $c = $func[0]; if (!array_key_exists(1, $func)) return false; $f = $func[1]; + $rargs = array_slice($func, 2); } else { return false; } @@ -139,6 +144,7 @@ class func { return false; } $func = [$c, false]; + if ($rargs) $args = cl::merge($rargs, $args); return true; } @@ -147,7 +153,7 @@ class func { * {@link self::verifix_class()} */ static function is_class($func, bool $strict=true, ?string &$reason=null): bool { - return self::verifix_class($func, $strict, $reason); + return self::verifix_class($func, $args, $strict, $reason); } ############################################################################# @@ -198,14 +204,16 @@ class func { * liée à une classe avant d'être utilisée * * @param bool $strict vérifier l'existence de la classe et de la méthode si + * @param array|null &$args * la méthode est liée (ne pas uniquement faire une vérification syntaxique) */ - static function verifix_static(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + static function verifix_static(&$func, ?array &$args = null, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { if ($strict) $reason = null; if ($func instanceof ReflectionMethod) { $bound = false; return true; } + $rargs = null; if (is_string($func)) { if (!self::_parse_c_static($func, $c, $f, $bound)) return false; $cf = [$c, $f]; @@ -252,6 +260,7 @@ class func { self::_parse_static($f); } $cf[1] = $f; + $rargs = array_slice($func, 2); } else { return false; } @@ -274,6 +283,7 @@ class func { } } $func = $cf; + if ($rargs) $args = cl::merge($rargs, $args); return true; } @@ -282,7 +292,7 @@ class func { * {@link self::verifix_static()} */ static function is_static($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { - return self::verifix_static($func, $strict, $bound, $reason); + return self::verifix_static($func, $args, $strict, $bound, $reason); } ############################################################################# @@ -335,12 +345,13 @@ class func { * @param bool $strict vérifier l'existence de la classe et de la méthode si * la méthode est liée (ne pas uniquement faire une vérification syntaxique) */ - static function verifix_method(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { + static function verifix_method(&$func, ?array &$args=null, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { if ($strict) $reason = null; if ($func instanceof ReflectionMethod) { $bound = false; return true; } + $rargs = null; if (is_string($func)) { if (!self::_parse_c_method($func, $c, $f, $bound)) return false; $cf = [$c, $f]; @@ -388,6 +399,7 @@ class func { self::_parse_method($f); } $cf[1] = $f; + $rargs = array_slice($func, 2); } else { return false; } @@ -410,6 +422,7 @@ class func { } } $func = $cf; + if ($rargs) $args = cl::merge($rargs, $args); return true; } @@ -418,7 +431,7 @@ class func { * {@link self::verifix_method()} */ static function is_method($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool { - return self::verifix_method($func, $strict, $bound, $reason); + return self::verifix_method($func, $args, $strict, $bound, $reason); } ############################################################################# @@ -452,13 +465,13 @@ class func { return new self(self::TYPE_METHOD, $func, $args, false); } } - if (self::verifix_function($func, $strict, $reason)) { + if (self::verifix_function($func, $args, $strict, $reason)) { return new self(self::TYPE_FUNCTION, $func, $args, false, $reason); - } elseif (self::verifix_class($func, $strict, $reason)) { + } elseif (self::verifix_class($func, $args, $strict, $reason)) { return new self(self::TYPE_CLASS, $func, $args, false, $reason); - } elseif (self::verifix_method($func, $strict, $bound, $reason)) { + } elseif (self::verifix_method($func, $args, $strict, $bound, $reason)) { return new self(self::TYPE_METHOD, $func, $args, $bound, $reason); - } elseif (self::verifix_static($func, $strict, $bound, $reason)) { + } elseif (self::verifix_static($func, $args, $strict, $bound, $reason)) { return new self(self::TYPE_STATIC, $func, $args, $bound, $reason); } return null; diff --git a/php/tests/php/funcTest.php b/php/tests/php/funcTest.php index f15ce27..a382660 100644 --- a/php/tests/php/funcTest.php +++ b/php/tests/php/funcTest.php @@ -295,14 +295,14 @@ namespace nulib\php { $workf = $func; $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_function($workf, true), "$msg --> verifix"); + self::assertSame($verifix1, func::verifix_function($workf, $args, true), "$msg --> verifix"); if ($verifix1) { self::assertSame($func1, $workf, "$msg --> func"); } $workf = $func; $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_function($workf, false), "$msg --> verifix"); + self::assertSame($verifix2, func::verifix_function($workf, $args, false), "$msg --> verifix"); if ($verifix2) { self::assertSame($func2, $workf, "$msg --> func"); } @@ -595,7 +595,7 @@ namespace nulib\php { $workf = $func; $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_static($workf, true, $bound), "$msg --> verifix"); + self::assertSame($verifix1, func::verifix_static($workf, $args, true, $bound), "$msg --> verifix"); if ($verifix1) { self::assertSame($bound1, $bound, "$msg --> bound"); self::assertSame($func1, $workf, "$msg --> func"); @@ -603,7 +603,7 @@ namespace nulib\php { $workf = $func; $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_static($workf, false, $bound), "$msg --> verifix"); + self::assertSame($verifix2, func::verifix_static($workf, $args, false, $bound), "$msg --> verifix"); if ($verifix2) { self::assertSame($bound2, $bound, "$msg --> bound"); self::assertSame($func2, $workf, "$msg --> func"); @@ -894,7 +894,7 @@ namespace nulib\php { $workf = $func; $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_method($workf, true, $bound), "$msg --> verifix"); + self::assertSame($verifix1, func::verifix_method($workf, $args, true, $bound), "$msg --> verifix"); if ($verifix1) { self::assertSame($bound1, $bound, "$msg --> bound"); self::assertSame($func1, $workf, "$msg --> func"); @@ -902,7 +902,7 @@ namespace nulib\php { $workf = $func; $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_method($workf, false, $bound), "$msg --> verifix"); + self::assertSame($verifix2, func::verifix_method($workf, $args, false, $bound), "$msg --> verifix"); if ($verifix2) { self::assertSame($bound2, $bound, "$msg --> bound"); self::assertSame($func2, $workf, "$msg --> func"); From 0a73ba371f472a903bdedb78cecb126c9cba87f1 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 30 Apr 2025 16:52:07 +0400 Subject: [PATCH 08/23] =?UTF-8?q?am=C3=A9liorer=20ergonomie=20de=20p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/p | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bin/p b/bin/p index aedfdfc..1c52283 100755 --- a/bin/p +++ b/bin/p @@ -29,6 +29,9 @@ function git_statuses() { done } +# sans arguments, il y a un comportement spécial +[ $# -eq 0 ] && NoArgs=1 || NoArgs= + chdir= all= composer= @@ -43,6 +46,13 @@ Si l'option -a est utilisée, ce script accepte comme arguments une liste de pat ) parse_args "$@"; set -- "${args[@]}" +if [ -n "$NoArgs" ]; then + # si aucun argument n'est spécifié et si on n'est pas dans un projet git, + # afficher le status de tous les sous répertoires + setx toplevel=git_get_toplevel + [ -z "$toplevel" ] && all=1 +fi + setx OrigCwd=pwd if [ -n "$chdir" ]; then cd "$chdir" || die From a418a87ac9781afc5385a4cf12c0328e1357edc8 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 2 May 2025 08:50:46 +0400 Subject: [PATCH 09/23] modifs.mineures sans commentaires --- php/src/A.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/src/A.php b/php/src/A.php index c7d982b..1f4b630 100644 --- a/php/src/A.php +++ b/php/src/A.php @@ -6,8 +6,8 @@ use Traversable; /** * Class A: gestion de tableaux ou d'instances de {@link IArrayWrapper} * - * contrairement à {@link cl}, les méthodes de cette classes sont plutôt conçues - * pour modifier le tableau en place + * cette classe reprend les méthodes de {@link cl} avec la différence que la + * modification est faite en place */ class A { /** From cc56dc9834e943a78b86969379cd9f06ed04d1c9 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 5 May 2025 15:34:11 +0400 Subject: [PATCH 10/23] renommer pdev en pmer --- bin/_merge82 | 2 +- bin/{pdev => pmer} | 0 lib/completion.d/pman | 8 ++++---- wip/pman.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename bin/{pdev => pmer} (100%) diff --git a/bin/_merge82 b/bin/_merge82 index 8a4c2bc..e372fb8 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 -a "git checkout dev74" "$@" +exec "$(dirname -- "$0")/pmer" --tech-merge -Bdev82 dev74 -a "git checkout dev74" "$@" diff --git a/bin/pdev b/bin/pmer similarity index 100% rename from bin/pdev rename to bin/pmer diff --git a/lib/completion.d/pman b/lib/completion.d/pman index e3dcb73..787e28b 100644 --- a/lib/completion.d/pman +++ b/lib/completion.d/pman @@ -1,6 +1,6 @@ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 -function __pman_pdev_branches() { +function __pman_pmer_branches() { local toplevel="$(git rev-parse --show-toplevel 2>/dev/null)" [ -n "$toplevel" ] || return 0 @@ -29,9 +29,9 @@ function __pman_pdev_branches() { ) } -function __pdev_completion() { +function __pmer_completion() { local cur _get_comp_words_by_ref cur - COMPREPLY=($(compgen -W "$(__pman_pdev_branches)" "$cur")) + COMPREPLY=($(compgen -W "$(__pman_pmer_branches)" "$cur")) } -complete -F __pdev_completion pdev +complete -F __pmer_completion pmer diff --git a/wip/pman.md b/wip/pman.md index 1bd316a..3968ad8 100644 --- a/wip/pman.md +++ b/wip/pman.md @@ -6,7 +6,7 @@ outil pour gérer les projets PHP projets dépendants du projet courant * pver: gestion des versions. calculer la prochaine version en respectant semver -* pdev: gérer les branches de features et hotfixes. +* pmer: gérer les branches de features et hotfixes. * prel: faire une release. ces outils peuvent agir sur les projets dépendants: faire une release sur un projet downstream, ou synchroniser la version depuis un projet upstream From 50aedea0e6815037748799a924fd98efe7fae5c9 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 5 May 2025 17:11:56 +0400 Subject: [PATCH 11/23] modifs.mineures sans commentaires --- php/src/db/pgsql/Pgsql.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php/src/db/pgsql/Pgsql.php b/php/src/db/pgsql/Pgsql.php index dbcbedf..efc84a4 100644 --- a/php/src/db/pgsql/Pgsql.php +++ b/php/src/db/pgsql/Pgsql.php @@ -81,6 +81,12 @@ class Pgsql implements IDatabase { #if ($tmp !== null) $dbconn = $tmp; #else $dbconn = ["" => $dbconn]; } + unset($dbconn["type"]); + $name = $dbconn["name"] ?? null; + if ($name !== null) { + $dbconn[""] = $name; + unset($dbconn["name"]); + } $params["dbconn"] = $dbconn; } # dbconn From 00effe4ee8da1fa0058b7658cf7fe87907001516 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 6 May 2025 07:50:16 +0400 Subject: [PATCH 12/23] modifs.mineures sans commentaires --- bin/pmer | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/pmer b/bin/pmer index 03e827c..979dd69 100755 --- a/bin/pmer +++ b/bin/pmer @@ -158,6 +158,7 @@ args=( " [source] CONFIGURATION + Le fichier .pman.conf contient la configuration des branches. Les variables supplémentaires suivantes peuvent être définies: BEFORE_MERGE_ From a587f99e42cfd778edf689bd50575e35a45e9542 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 6 May 2025 16:31:10 +0400 Subject: [PATCH 13/23] installer completion pour pman --- lib/uinst/conf | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/uinst/conf b/lib/uinst/conf index 6f4d212..8ed9698 100644 --- a/lib/uinst/conf +++ b/lib/uinst/conf @@ -1,6 +1,20 @@ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$@" || exit 1 +cd "$srcdir" # supprimer les fichiers de VCS -rm -rf "$srcdir/.git" +rm -rf .git + +# completion +fromdir=lib/completion.d +todir="$HOME/etc/completion.d" +mkdir -p "$todir" +for file in pman; do + from="$fromdir/$file" + to="$todir/$file" + if [ -f "$to" ]; then + diff -q "$from" "$to" && continue + fi + cp "$from" "$to" +done From c78196450e6609181e33935577ebf4a828a8be03 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 6 May 2025 17:03:07 +0400 Subject: [PATCH 14/23] modifs.mineures sans commentaires --- php/src/db/sqlite/SqliteStorage.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/php/src/db/sqlite/SqliteStorage.php b/php/src/db/sqlite/SqliteStorage.php index 4621cb2..7495b46 100644 --- a/php/src/db/sqlite/SqliteStorage.php +++ b/php/src/db/sqlite/SqliteStorage.php @@ -40,12 +40,20 @@ class SqliteStorage extends CapacitorStorage { return new _sqliteMigration($migrations, $channel->getName()); } - function channelExists(string $name): bool { - return null !== $this->db->get([ - "select name", + function channelExists(string $name, ?array &$row=null): bool { + $row = $this->db->one([ + "select", "from" => static::CHANNELS_TABLE, "where" => ["name" => $name], ]); + return $row !== null; + } + + function getChannels(): iterable { + return $this->db->all([ + "select", + "from" => static::CHANNELS_TABLE, + ]); } protected function _addToChannelsSql(CapacitorChannel $channel): array { From b8a3d7ae77a95b91a3d2b44751b021e69322ca5f Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 7 May 2025 10:46:49 +0400 Subject: [PATCH 15/23] modifs.mineures sans commentaires --- php/src/cl.php | 29 +++++++++++++++++++++++++++++ php/src/db/_private/_select.php | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/php/src/cl.php b/php/src/cl.php index a1073ee..ebbcca9 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -60,6 +60,35 @@ class cl { return $default; } + /** + * retourner la valeur à l'index $index, ou $default si le tableau est null + * ou vide, ou si l'index n'existe pas + * + * ici, l'index est le rang de la clé: 0 pour la première clé du tableau, 1 + * pour la deuxième, etc. + * + * si $index est négatif, il est compté à partir de la fin du tableau + */ + static final function nth(?iterable $iterable, int $index, $default=null) { + if ($iterable === null) return $default; + if ($index < 0 && !is_array($iterable)) { + $iterable = iterator_to_array($iterable, false); + } + if (is_array($iterable)) { + $keys = array_keys($iterable); + $count = count($keys); + while ($index < 0) $index += $count; + $key = $keys[$index] ?? null; + if ($key === null) return $default; + return $iterable[$key]; + } + foreach ($iterable as $value) { + if ($index === 0) return $value; + $index--; + } + return $default; + } + /** * retourner la dernière valeur de $array ou $default si le tableau est null * ou vide diff --git a/php/src/db/_private/_select.php b/php/src/db/_private/_select.php index 80b0460..1e7f1d0 100644 --- a/php/src/db/_private/_select.php +++ b/php/src/db/_private/_select.php @@ -23,7 +23,8 @@ class _select extends _common { return preg_match("/^select\b/i", $sql); } - private static function add_prefix(string $col, ?string $prefix): string { + private static function add_prefix(?string $col, ?string $prefix): string { + $col ??= "null"; if ($prefix === null) return $col; if (strpos($col, ".") !== false) return $col; return "$prefix$col"; From bbbe10191860c819925f805a898baf8029fe48da Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 8 May 2025 06:58:54 +0400 Subject: [PATCH 16/23] modifs.mineures sans commentaires --- php/src/cl.php | 4 ++-- php/tests/clTest.php | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/php/src/cl.php b/php/src/cl.php index ebbcca9..78dcb9b 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -241,7 +241,7 @@ class cl { } /** - * obtenir la liste des clés finalement obtenues après l'appel à + * obtenir la liste des clés qui seraient finalement obtenues après l'appel à * {@link self::select()} avec le mapping spécifié */ static final function selected_keys(?array $mappings): array { @@ -284,7 +284,7 @@ class cl { * $includes qui ne sont pas mentionnées dans $excludes. * * - si $includes===null && $excludes===null, retourner le tableau inchangé - * - si $includes vaut null, prendre toutes les clés + * - si $includes vaut null, c'est comme si toutes les clés étaient incluses * */ static final function xselect($array, ?array $includes, ?array $excludes=null): ?array { diff --git a/php/tests/clTest.php b/php/tests/clTest.php index d2b834f..bedec17 100644 --- a/php/tests/clTest.php +++ b/php/tests/clTest.php @@ -12,10 +12,10 @@ class clTest extends TestCase { } function test_same_keys() { $array = ["a" => 42, "b" => "tesxt"]; $arrayKeys = array_keys($array); - $xarray = ["parasite0", "a" => 42, "parasite1", "b" => "tesxt"]; $xarrayKeys = array_keys($array); + $missingArray = ["c" => true]; $missingArrayKeys = array_keys($missingArray); $ref = ["a" => "int", "b" => "text"]; $refKeys = array_keys($ref); - $missingArray = ["c" => true]; $missingKeys = array_keys($missingArray); - $missingRef = ["c" => "bool"]; $missingKeys = array_keys($missingRef); + $missingRef = ["c" => "bool"]; $missingRefKeys = array_keys($missingRef); + $xarray = ["parasite0", "a" => 42, "parasite1", "b" => "tesxt"]; $this->checkKeys(null, null, true, [], [], []); $this->checkKeys(null, [], true, [], [], []); @@ -29,8 +29,8 @@ class clTest extends TestCase { $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(cl::merge($array, $missingArray), $ref, true, $arrayKeys, $missingArrayKeys, []); + $this->checkKeys($array, cl::merge($ref, $missingRef), false, $arrayKeys, [], $missingRefKeys); $this->checkKeys($xarray, $ref, false, $arrayKeys, [0, 1], []); } From dd3006e05d187b4bd07d2e9c5519a6ba277db977 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 8 May 2025 22:29:25 +0400 Subject: [PATCH 17/23] bug --- bin/templ.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/templ.sql b/bin/templ.sql index fb22c73..14c071c 100755 --- a/bin/templ.sql +++ b/bin/templ.sql @@ -29,7 +29,7 @@ for file in "$@"; do estep "Création de $file" cat >"$file" < Date: Fri, 9 May 2025 10:27:06 +0400 Subject: [PATCH 18/23] =?UTF-8?q?int=C3=A9grer=20les=20m=C3=A9thodes=20de?= =?UTF-8?q?=20Cursor=20et=20KeyAccess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/src/A.php | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ php/src/cl.php | 85 ++++++++++++++++++++++++++++++++++---- 2 files changed, 186 insertions(+), 7 deletions(-) diff --git a/php/src/A.php b/php/src/A.php index 1f4b630..253592b 100644 --- a/php/src/A.php +++ b/php/src/A.php @@ -1,6 +1,7 @@ + * $array = ["first", "second"] + * A::ensure_assoc($array, ["a", "b"]); + * // returns ["a" => "first", "b" => "second"] + * + */ + static final function ensure_assoc(?array &$array, array $keys, ?array $params=null): void { + $prefix = $params["key_prefix"] ?? null; + $suffix = $params["key_suffix"] ?? null; + $index = 0; + foreach ($keys as $key) { + if ($prefix !== null || $suffix !== null) { + $destKey = "$prefix$key$suffix"; + } else { + # préserver les clés numériques + $destKey = $key; + } + if ($array !== null && array_key_exists($destKey, $array)) continue; + while (in_array($index, $keys, true)) { + $index++; + } + if ($array !== null && array_key_exists($index, $array)) { + $array[$destKey] = $array[$index]; + unset($array[$index]); + $index++; + } + } + } + + /** + * s'assurer que $array contient toutes les clés de $defaults, avec la valeur + * par défaut le cas échéant + * + * $missings est un tableau indiquant des valeurs qui si elles sont dans + * $array, signifie que la clé correspondante doit être considérée comme + * inexistante (et donc remplacée par la valeur de $defaults) + */ + static final function ensure_keys(?array &$array, array $defaults, ?array $missings=null, ?array $params=null): void { + $keys = array_keys($defaults); + $prefix = $params["key_prefix"] ?? null; + $suffix = $params["key_suffix"] ?? null; + foreach ($keys as $key) { + $destKey = "$prefix$key$suffix"; + $haveMissing = $missings !== null && array_key_exists($key, $missings); + if ($array === null || !array_key_exists($destKey, $array)) { + $array[$destKey] = $defaults[$key]; + } elseif ($haveMissing && $array[$destKey] === $missings[$key]) { + $array[$destKey] = $defaults[$key]; + } + } + } + + /** + * supprimer dans $array les clés dont les valeurs correspondent au tableau + * $missings + */ + static final function delete_missings(?array &$array, array $missings, ?array $params=null): void { + $prefix = $params["key_prefix"] ?? null; + $suffix = $params["key_suffix"] ?? null; + foreach ($missings as $key => $missing) { + $destKey = "$prefix$key$suffix"; + if (array_key_exists($destKey, $array) && $array[$destKey] === $missing) { + unset($array[$destKey]); + } + } + } + + /** + * s'assurer que les clés dans $array sont dans le même ordre que dans $keys + * + * les clés supplémentaires sont poussées à la fin du tableau + */ + static final function ensure_order(?array &$array, array $keys, ?array $params=null): void { + if ($array === null) return; + + $prefix = $params["key_prefix"] ?? null; + $suffix = $params["key_suffix"] ?? null; + if ($prefix !== null || $suffix !== null) { + foreach ($keys as &$key) { + $key = "$prefix$key$suffix"; + }; unset($key); + } + + $destKeys = array_keys($array); + $keyCount = count($keys); + if (array_slice($destKeys, 0, $keyCount) === $keys) { + # si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire + return; + } + + $ordered = []; + foreach ($keys as $key) { + if (array_key_exists($key, $array)) { + $ordered[$key] = $array[$key]; + unset($array[$key]); + } + } + $preserveKeys = $params["preserve_keys"] ?? false; + if ($preserveKeys) $array = cl::merge2($ordered, $array); + else $array = array_merge($ordered, $array); + } } diff --git a/php/src/cl.php b/php/src/cl.php index 78dcb9b..2c2bac1 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -398,15 +398,86 @@ class cl { ############################################################################# - static final function map($func, ?iterable $array): array { - $result = []; - if ($array !== null) { - $func = func::with($func); - foreach ($array as $key => $value) { - $result[$key] = $func->invoke([$value, $key]); + /** + * tester si $array satisfait les conditions de $filter + * - $filter est un scalaire, le transformer en [$filter] + * - sinon $filter doit être un tableau de scalaires + * + * les règles des conditions sont les suivantes: + * - une valeur séquentielle $key est équivalente à la valeur associative + * $key => true + * - une valeur associative $key => bool indique que la clé correspondante ne + * doit pas (resp. doit) exister selon que bool vaut false (resp. true) + * - une valeur associative $key => $value indique que la clé correspondante + * doit exiter avec la valeur spécifiée + */ + static final function filter(?array $array, $filter): bool { + if ($filter === null) return false; + if (!is_array($filter)) $filter = [$filter]; + if (!$filter) return false; + + $index = 0; + foreach ($filter as $key => $value) { + if ($key === $index) { + $index++; + if ($array === null) return false; + if (!array_key_exists($value, $array)) return false; + } elseif (is_bool($value)) { + if ($value) { + if ($array === null || !array_key_exists($key, $array)) return false; + } else { + if ($array !== null && array_key_exists($key, $array)) return false; + } + } else { + if ($array === null) return false; + if (!array_key_exists($key, $array)) return false; + if ($array[$key] !== $value) return false; } } - return $result; + return true; + } + + /** + * mapper le tableau source $array selon les règles suivantes illustrées dans + * l'exemple suivant: + * si + * $map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null] + * alors retourner le tableau + * ["a" => $array["a"], "b" => $array["x"], "c" => "y", "d" => null] + * + * si une fonction est utilisée, sa signature est + * function(mixed $value, string|int $key, ?array $array) + */ + static function map(?array $array, ?array $map): ?array { + if ($map === null) return $array; + $index = 0; + $mapped = []; + foreach ($map as $key => $value) { + if ($key === $index) { + $index++; + if ($value === null) $mapped[] = null; + else $mapped[$value] = cl::get($array, $value); + } elseif (is_callable($value)) { + $func = func::with($value); + $value = cl::get($array, $key); + $mapped[$key] = $func->invoke([$value, $key, $array]); + } else { + if ($value === null) $mapped[$key] = null; + else $mapped[$key] = cl::get($array, $value); + } + } + return $mapped; + } + + static final function mapf(?iterable $items, $func): array { + $mapped = []; + if ($items !== null) { + $func = func::with($func); + foreach ($items as $key => $item) { + $mapped[$key] = $func->invoke([$item, $key, $items]); + } + } + return $mapped; } ############################################################################# From 2e026daeda20c0574f630c74f66cdee4c79be263 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 05:43:55 +0400 Subject: [PATCH 19/23] =?UTF-8?q?l'option=20-ww=20affiche=20la=20diff?= =?UTF-8?q?=C3=A9rence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bash/src/pman.sh | 6 ++++++ bin/pmer | 18 +++++++++++++++--- bin/prel | 18 +++++++++++++++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/bash/src/pman.sh b/bash/src/pman.sh index f2f5d3d..4a2d928 100644 --- a/bash/src/pman.sh +++ b/bash/src/pman.sh @@ -84,6 +84,12 @@ function _list_commits() { _filter_rel } +function _show_diff() { + local source="${1:-$SrcBranch}" dest="${2:-$DestBranch}" mergebase + setx mergebase=git merge-base "$dest" "$source" + git diff ${_sd_COLOR:+--color=$_sd_COLOR} "$mergebase..$source" +} + function _scripte() { echo >>"$script" echo "$comment$(qvals "$@")" >>"$script" diff --git a/bin/pmer b/bin/pmer index 979dd69..9a7daf8 100755 --- a/bin/pmer +++ b/bin/pmer @@ -11,8 +11,19 @@ function show_action() { local commits setx commits=_list_commits if [ -n "$commits" ]; then - einfo "Commits à fusionner $SrcBranch --> $DestBranch" - eecho "$commits" + if [ $ShowLevel -ge 2 ]; then + { + echo "\ +# Commits à fusionner $SrcBranch --> $DestBranch + +$commits +" + _sd_COLOR=always _show_diff + } | less -eRF + else + einfo "Commits à fusionner $SrcBranch --> $DestBranch" + eecho "$commits" + fi fi } @@ -148,6 +159,7 @@ ConfigFile= _Fake= _KeepScript= action=merge +ShowLevel=0 TechMerge= SquashMsg= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= @@ -177,7 +189,7 @@ 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" --fake _Fake=1 "++option non documentée" --keep-script _KeepScript=1 "++option non documentée" - -w,--show action=show "\ + -w,--show '$action=show; inc@ ShowLevel' "\ lister les modifications qui seraient fusionnées dans la branche destination" -b,--rebase action=rebase "\ lancer git rebase -i sur la branche source. cela permet de réordonner les diff --git a/bin/prel b/bin/prel index e1af6eb..2ec3a31 100755 --- a/bin/prel +++ b/bin/prel @@ -11,8 +11,19 @@ function show_action() { local commits setx commits=_list_commits if [ -n "$commits" ]; then - einfo "Commits à fusionner $SrcBranch --> $DestBranch" - eecho "$commits" + if [ $ShowLevel -ge 2 ]; then + { + echo "\ +# Commits à fusionner $SrcBranch --> $DestBranch + +$commits +" + _sd_COLOR=always _show_diff + } | less -eRF + else + einfo "Commits à fusionner $SrcBranch --> $DestBranch" + eecho "$commits" + fi fi } @@ -194,6 +205,7 @@ ConfigFile= _Fake= _KeepScript= action=release +ShowLevel=0 [ -z "$PMAN_NO_MERGE" ] && Merge=1 || Merge= [ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= Version= @@ -222,7 +234,7 @@ 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" --fake _Fake=1 "++option non documentée" --keep-script _KeepScript=1 "++option non documentée" - -w,--show action=show "\ + -w,--show '$action=show; inc@ ShowLevel' "\ lister les modifications qui seraient intégrées dans la release" --release action=release "++\ créer la release. From d274a6528a3dc363183cc736ea0d853d9f994c5d Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 06:21:02 +0400 Subject: [PATCH 20/23] =?UTF-8?q?am=C3=A9liorer=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/src/app/RunFile.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/php/src/app/RunFile.php b/php/src/app/RunFile.php index d76beb9..bd34357 100644 --- a/php/src/app/RunFile.php +++ b/php/src/app/RunFile.php @@ -460,7 +460,7 @@ class RunFile { $exitcode = null; $message = [ "status" => "$desc: EN COURS pid $data[pid]", - "started" => "Démarrée depuis $dateStart ($sinceStart)", + "started" => "Démarrée $sinceStart le $dateStart", "action" => $action, ]; } elseif ($this->isStopped($data)) { @@ -471,8 +471,9 @@ class RunFile { elseif ($exitcode === 0) $type = "success"; else $type = "danger"; $message = [ - "status" => "$desc: TERMINEE$duration", + "status" => "$desc: TERMINEE", "stopped" => "Arrêtée $sinceStop le $dateStop", + "duration" => $duration, "result" => $result, ]; } else { From 23358180acbe84b0681def1fd5380a94dd21e1ae Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 11:21:58 +0400 Subject: [PATCH 21/23] modifs.mineures sans commentaires --- bin/pman | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pman b/bin/pman index 80a1021..123f193 100755 --- a/bin/pman +++ b/bin/pman @@ -78,7 +78,7 @@ function init_repo_action() { } function init_config_action() { - local -a push_branches; config + local -a push_branches; local config [ -f .pman.conf -a -z "$ForceCreate" ] && die "La configuration pman a déjà été initialisée" From c2b1d23d3650c7d1756672ae897dac3160733482 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 15:28:47 +0400 Subject: [PATCH 22/23] Init changelog & version 0.5.1p74 --- CHANGES.md | 13 +++++++++++++ VERSION.txt | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1f6a6e8..047411f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,16 @@ +## Release 0.5.1p74 du 12/05/2025-15:28 + +* `d274a65` améliorer status +* `2e026da` l'option -ww affiche la différence +* `8e7e59c` intégrer les méthodes de Cursor et KeyAccess +* `a587f99` installer completion pour pman +* `cc56dc9` renommer pdev en pmer +* `0a73ba3` améliorer ergonomie de p +* `aef0533` ajout str::split +* `87e262c` ajout cl::delv +* `a371a68` maj doc +* `d706122` ajout infos release + ## Release 0.5.0p82 du 30/04/2025-04:33 ## Release 0.5.0p74 du 30/04/2025-04:31 diff --git a/VERSION.txt b/VERSION.txt index 8f0916f..4b9fcbe 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.5.0 +0.5.1 From 49d7fafc07f26ab5ef0acbd9c4f8d7427e9486ad Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 15:31:32 +0400 Subject: [PATCH 23/23] Init changelog & version 0.5.1p82 --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 047411f..e2f1c9d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,5 @@ +## Release 0.5.1p82 du 12/05/2025-15:31 + ## Release 0.5.1p74 du 12/05/2025-15:28 * `d274a65` améliorer status