<pman>Intégration de la branche dev74

This commit is contained in:
Jephté Clain 2025-03-02 19:24:09 +04:00
commit f1f033e0e9
11 changed files with 312 additions and 25 deletions

8
.pman.yml Normal file
View File

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

View File

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

View File

@ -5,15 +5,23 @@
# les branches sont mergées dans cet ordre: # les branches sont mergées dans cet ordre:
# upstream --> develop --> [release -->] main --> dist # upstream --> develop --> [release -->] main --> dist
# feature _/ hotfix _/ # feature _/ hotfix _/
# branche upstream
UPSTREAM= UPSTREAM=
# branches de développement
DEVELOP=develop DEVELOP=develop
FEATURE=wip/ FEATURE=wip/
# branche de préparation de release
RELEASE=release- RELEASE=release-
# branche de release
MAIN=master MAIN=master
TAG_PREFIX= TAG_PREFIX=
TAG_SUFFIX= TAG_SUFFIX=
# branche de hotfix
HOTFIX=hotfix- HOTFIX=hotfix-
# branche de distribution
DIST= DIST=
# désactiver les releases automatiques?
NOAUTO= NOAUTO=
CONFIG_VARS=( CONFIG_VARS=(
@ -210,6 +218,9 @@ function load_branches() {
} }
function load_config() { function load_config() {
if [ "${ConfigFile#::}" != "$ConfigFile" ]; then
ConfigFile="$NULIBDIR/bash/src/pman${ConfigFile#::}.conf.sh"
fi
if [ -n "$ConfigFile" ]; then if [ -n "$ConfigFile" ]; then
source "$ConfigFile" || die || return source "$ConfigFile" || die || return
elif [ -n "$ConfigBranch" ]; then elif [ -n "$ConfigBranch" ]; then
@ -224,12 +235,16 @@ function load_config() {
elif [ -f .pman.conf ]; then elif [ -f .pman.conf ]; then
ConfigFile="$(pwd)/.pman.conf" ConfigFile="$(pwd)/.pman.conf"
source "$ConfigFile" source "$ConfigFile"
elif [ -n "${MYNAME#prel}" ]; then elif [ -n "$1" -a -n "${MYNAME#$1}" ]; then
ConfigFile="$NULIBDIR/bash/src/pman${MYNAME#$1}.conf.sh" ConfigFile="$NULIBDIR/bash/src/pman${MYNAME#$1}.conf.sh"
source "$ConfigFile" source "$ConfigFile"
else else
ConfigFile="$NULIBDIR/bash/src/pman.conf.sh" ConfigFile="$NULIBDIR/bash/src/pman.conf.sh"
fi fi
# S'assurer que nulib est dans le PATH pour que les scripts utilisateurs
# puissent utiliser les outils fournis
export PATH="$NULIBDIR/bin:$PATH"
} }
################################################################################ ################################################################################

View File

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

View File

@ -134,7 +134,15 @@ SquashMsg=
[ -z "$PMAN_NO_DELETE" ] && Delete=1 || Delete= [ -z "$PMAN_NO_DELETE" ] && Delete=1 || Delete=
args=( args=(
"fusionner la branche source dans la branche destination correspondante" "fusionner la branche source dans la branche destination correspondante"
" [source]" " [source]
CONFIGURATION
Le fichier .pman.conf contient la configuration des branches.Les variables
supplémentaires suivantes peuvent être définies:
AFTER_MERGE_<srcType>
AFTER_DELETE_<srcType>
AFTER_PUSH_<destType>
xxxType valant UPSTREAM, DEVELOP, FEATURE, RELEASE, MAIN, HOTFIX, DIST"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine à partir de laquelle les branches distantes sont considérées" origine à partir de laquelle les branches distantes sont considérées"

View File

@ -34,16 +34,12 @@ function show_action() {
# Initialisation # Initialisation
################################################################################ ################################################################################
function init_repo_action() { function _init_config() {
[ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé" if [ ! -f .pman.conf -o -n "$ForceCreate" ]; then
local -a push_branches
if [ ! -f .pman.conf ]; then
ac_set_tmpfile config ac_set_tmpfile config
cp "$ConfigFile" "$config" cp "$ConfigFile" "$config"
"${EDITOR:-nano}" "$config" "${EDITOR:-nano}" "$config"
[ -s "$config" ] || exit_with ewarn "Initialisation du dépôt annulée" [ -s "$config" ] || return 1
cp "$config" .pman.conf cp "$config" .pman.conf
if testdiff .pman.conf "$ConfigFile"; then if testdiff .pman.conf "$ConfigFile"; then
@ -59,6 +55,15 @@ function init_repo_action() {
.*.swp" .*.swp"
git add .gitignore git add .gitignore
fi fi
return 0
}
function init_repo_action() {
[ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé"
local -a push_branches
_init_config || exit_with ewarn "Initialisation du dépôt annulée"
einfo "Création de la branche $MAIN" einfo "Création de la branche $MAIN"
git symbolic-ref HEAD "refs/heads/$MAIN" git symbolic-ref HEAD "refs/heads/$MAIN"
@ -72,6 +77,18 @@ function init_repo_action() {
_push_branches _push_branches
} }
function init_config_action() {
[ -f .pman.conf ] && die "La configuration pman a déjà été initialisée"
local -a push_branches
_init_config || exit_with ewarn "Initialisation de la configuration annulée"
git commit -m "configuration pman"
push_branches+=("$CurrentBranch")
_push_branches
}
function init_develop_action() { function init_develop_action() {
if [ -z "$DevelopBranch" ]; then if [ -z "$DevelopBranch" ]; then
[ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie" [ -n "$DEVELOP" ] || die "La branche DEVELOP n'a pas été définie"
@ -174,6 +191,7 @@ function init_action() {
local what="${1:-develop}"; shift local what="${1:-develop}"; shift
case "$what" in case "$what" in
init|repo|r) init_repo_action "$@";; init|repo|r) init_repo_action "$@";;
config) init_config_action "$@";;
main|m) git checkout -q "$MAIN";; main|m) git checkout -q "$MAIN";;
develop|dev|d) init_develop_action "$@";; develop|dev|d) init_develop_action "$@";;
upstream|up|u) init_upstream_action "$@";; upstream|up|u) init_upstream_action "$@";;
@ -192,9 +210,10 @@ ConfigFile=
action=init action=init
Origin= Origin=
Push=1 Push=1
ForceCreate=
args=( args=(
"gérer un projet git" "gérer un projet git"
"repo|develop|upstream|dist "repo|config|develop|upstream|dist
INITIALISATION INITIALISATION
@ -219,6 +238,8 @@ fichier de configuration des branches. cette option est prioritaire sur --config
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
-w,--show-config action=show "++\ -w,--show-config action=show "++\
afficher la configuration chargée" afficher la configuration chargée"
--composer-select-profile action=composer_select_profile "\
sélectionner le profil composer spécifié en argument"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine vers laquelle pousser les branches" origine vers laquelle pousser les branches"
-n,--no-push Push= "\ -n,--no-push Push= "\
@ -226,6 +247,8 @@ ne pas pousser les branches vers leur origine après leur création"
--push Push=1 "++\ --push Push=1 "++\
pousser les branches vers leur origine après leur création. pousser les branches vers leur origine après leur création.
c'est l'option par défaut" c'est l'option par défaut"
-f,--force-create ForceCreate=1 "\
Avec config, forcer la (re)création du fichier .pman.conf"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -244,6 +267,9 @@ init)
git_ensure_cleancheckout git_ensure_cleancheckout
init_action "$@" init_action "$@"
;; ;;
composer_select_profile)
exec "$MYDIR/_pman-$action.php" "$@"
;;
*) *)
die "$action: action non implémentée" die "$action: action non implémentée"
;; ;;

View File

@ -42,6 +42,9 @@ function create_release_action() {
merge_hotfix_action "$@"; return $? merge_hotfix_action "$@"; return $?
fi fi
[ -n "$ManualRelease" ] && ewarn "\
L'option --no-merge a été forcée puisque ce dépôt ne supporte pas les releases automatiques"
if [ -z "$Version" -a -n "$CurrentVersion" -a -f VERSION.txt ]; then if [ -z "$Version" -a -n "$CurrentVersion" -a -f VERSION.txt ]; then
Version="$(<VERSION.txt)" Version="$(<VERSION.txt)"
Tag="$TAG_PREFIX$Version$TAG_SUFFIX" Tag="$TAG_PREFIX$Version$TAG_SUFFIX"
@ -182,7 +185,15 @@ CurrentVersion=
ForceCreate= ForceCreate=
args=( args=(
"faire une nouvelle release à partir de la branche source" "faire une nouvelle release à partir de la branche source"
" -v VERSION [source]" " -v VERSION [source]
CONFIGURATION
Le fichier .pman.conf contient la configuration des branches
Les variables supplémentaires suivantes peuvent être définies:
AFTER_CREATE_RELEASE
AFTER_MERGE_RELEASE
AFTER_PUSH_RELEASE"
-d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations"
-O:,--origin Origin= "++\ -O:,--origin Origin= "++\
origine à partir de laquelle les branches distantes sont considérées" origine à partir de laquelle les branches distantes sont considérées"
@ -208,11 +219,11 @@ ne pas pousser les branches vers leur origine après la création de la release"
--push Push=1 "++\ --push Push=1 "++\
pousser les branches vers leur origine après la création de la release. pousser les branches vers leur origine après la création de la release.
c'est l'option par défaut" c'est l'option par défaut"
-v:,--version Version= "\ -v:,--version:VERSION Version= "\
spécifier la version de la release à créer" spécifier la version de la release à créer"
-C,--current-version CurrentVersion=1 "++\ -C,--current-version CurrentVersion=1 "++\
si aucune version n'est spécifiée, prendre la version présente dans le fichier VERSION.txt" si aucune version n'est spécifiée, prendre la version présente dans le fichier VERSION.txt"
-f:,--force-create ForceCreate= "\ -f,--force-create ForceCreate= "\
forcer la création de la release même si le tag correspond à la version existe déjà" forcer la création de la release même si le tag correspond à la version existe déjà"
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -223,10 +234,8 @@ load_branches all
load_config "$MYNAME" load_config "$MYNAME"
load_branches current "$1"; shift load_branches current "$1"; shift
if [ -n "$Merge" -a -n "$NOAUTO" ]; then [ -n "$Merge" -a -n "$NOAUTO" ] && ManualRelease=1 || ManualRelease=
ewarn "L'option --no-merge a été forcée puisque ce dépôt ne supporte pas les releases automatiques" [ -n "$ManualRelease" ] && Merge=
Merge=
fi
[ -z "$Merge" ] && Push= [ -z "$Merge" ] && Push=
CantPush= CantPush=

View File

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

View File

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

View File

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

Binary file not shown.