Compare commits

..

8 Commits
dev74 ... dev82

27 changed files with 292 additions and 254 deletions

1
.idea/nulib-base.iml generated
View File

@ -4,7 +4,6 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/php/src" isTestSource="false" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/php/tests" isTestSource="true" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/php/vendor" />
</content>
<orderEntry type="inheritedJdk" />

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpTestFrameworkVersionCache">
<tools_cache>
<tool tool_name="PHPUnit">
<cache>
<versions>
<info id="Local/php/vendor/autoload.php" version="9.6.23" />
</versions>
</cache>
</tool>
</tools_cache>
</component>
</project>

12
.idea/php.xml generated
View File

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetector">
<phpmd_settings>
<phpmd_by_interpreter asDefaultInterpreter="true" interpreter_id="846389f7-9fb5-4173-a868-1dc6b8fbb3fa" timeout="30000" />
</phpmd_settings>
</component>
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
@ -15,11 +10,6 @@
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpCodeSniffer">
<phpcs_settings>
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="846389f7-9fb5-4173-a868-1dc6b8fbb3fa" timeout="30000" />
</phpcs_settings>
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/php/vendor/symfony/polyfill-ctype" />
@ -65,7 +55,7 @@
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/php/vendor/autoload.php" phpunit_phar_path="" />
<PhpUnitSettings configuration_file_path="$PROJECT_DIR$/php/vendor/sebastian/object-enumerator/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">

10
.idea/phpunit.xml generated
View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPUnit">
<option name="directories">
<list>
<option value="$PROJECT_DIR$/tests" />
</list>
</option>
</component>
</project>

View File

@ -1,11 +1,11 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
UPSTREAM=
DEVELOP=dev74
FEATURE=wip74/
RELEASE=rel74-
MAIN=dist74
TAG_SUFFIX=p74
HOTFIX=hotf74-
UPSTREAM=dev74
DEVELOP=dev82
FEATURE=wip82/
RELEASE=rel82-
MAIN=dist82
TAG_SUFFIX=p82
HOTFIX=hotf82-
DIST=
NOAUTO=

View File

@ -4,5 +4,5 @@
RUNPHP=
# Si RUNPHP n'est pas défini, les variables suivantes peuvent être définies
DIST=d11
DIST=d12
#REGISTRY=pubdocker.univ-reunion.fr/dist

2
.udir
View File

@ -9,7 +9,7 @@ uinc_options=()
uinc_args=()
preconfig_scripts=()
configure_variables=(dest)
configure_dest_for=(lib/profile.d/nulib)
configure_dest_for=(lib/profile.d/nulib-base)
config_scripts=(lib/uinst/conf)
install_profiles=true
profiledir=lib/profile.d

View File

@ -38,8 +38,6 @@ echo "commit=$commit"
# reprendre la valeur affichée par la précédente commande
commit=XXX
pu
git checkout dev74
git cherry-pick "$commit"

View File

@ -18,12 +18,12 @@
"nulib/php": "*"
},
"require": {
"symfony/yaml": "^5.0",
"symfony/yaml": "^7.1",
"ext-json": "*",
"php": "^7.4"
"php": "^8.2"
},
"require-dev": {
"nulib/tests": "^7.4",
"nulib/tests": "^8.2",
"ext-posix": "*",
"ext-pcntl": "*",
"ext-curl": "*",

View File

@ -111,8 +111,6 @@ class CapacitorChannel implements ITransactor {
$def = strval($def);
if (preg_match('/\bprimary\s+key\b/i', $def)) {
$primaryKeys[] = $col;
} elseif ($def === "genserial") {
$primaryKeys[] = $col;
}
}
}
@ -257,10 +255,6 @@ class CapacitorChannel implements ITransactor {
* Retourner la clé primaire par cette méthode est l'unique moyen de
* déclencher une mise à jour plutôt qu'une nouvelle création.
*
* Bien que ce ne soit pas prévu à la base, si on veut modifier $item dans
* cette méthode pour des raisons pratiques, il suffit de retournerla valeur
* modifiée avec la clé "item"
*
* Retourner [false] pour annuler le chargement
*/
function getItemValues($item): ?array {
@ -341,7 +335,7 @@ class CapacitorChannel implements ITransactor {
* Retourner [false] pour annuler le chargement (la ligne n'est pas créée)
*
* Si $item est modifié dans cette méthode, il est possible de le retourner
* avec la clé "item" pour mettre à jour la colonne correspondante.
* avec la clé "item" pour mettre à jour la ligne correspondante.
*
* la création ou la mise à jour est uniquement décidée en fonction des
* valeurs calculées par {@link self::getItemValues()}. Bien que cette méthode

View File

@ -1,7 +1,6 @@
<?php
namespace nulib\db;
use nulib\A;
use nulib\cl;
use nulib\db\_private\_migration;
use nulib\php\func;
@ -33,43 +32,21 @@ abstract class CapacitorStorage {
return $channel;
}
const PRIMARY_KEY_DEFINITION = [
"id_" => "genserial",
];
/** DOIT être défini dans les classes dérivées */
const PRIMARY_KEY_DEFINITION = null;
# les définitions sont par défaut pour MariaDB/MySQL
const SERDATA_DEFINITION = "mediumtext";
const SERSUM_DEFINITION = "varchar(40)";
const SERTS_DEFINITION = "datetime";
const GENSERIAL_DEFINITION = "integer primary key auto_increment";
const GENLIC_DEFINITION = "varchar(80)";
const GENLIB_DEFINITION = "varchar(255)";
const GENTEXT_DEFINITION = "mediumtext";
const GENBOOL_DEFINITION = "integer(1)";
const GENUUID_DEFINITION = "varchar(36)";
protected static function gencol($def): string {
protected static function sercol($def): string {
if (!is_string($def)) $def = strval($def);
$def = trim($def);
$parts = preg_split('/\s+/', $def, 2);
if (count($parts) == 2) {
$def = $parts[0];
$rest = " $parts[1]";
} else {
$rest = null;
}
switch ($def) {
case "serdata": $def = static::SERDATA_DEFINITION; break;
case "sersum": $def = static::SERSUM_DEFINITION; break;
case "serts": $def = static::SERTS_DEFINITION; break;
case "genserial": $def = static::GENSERIAL_DEFINITION; break;
case "genlic": $def = static::GENLIC_DEFINITION; break;
case "genlib": $def = static::GENLIB_DEFINITION; break;
case "gentext": $def = static::GENTEXT_DEFINITION; break;
case "genbool": $def = static::GENBOOL_DEFINITION; break;
case "genuuid": $def = static::GENUUID_DEFINITION; break;
}
return "$def$rest";
return $def;
}
const COLUMN_DEFINITIONS = [
@ -104,7 +81,7 @@ abstract class CapacitorStorage {
$mindex++;
} else {
if ($mdef) {
$definitions[$mcol] = self::gencol($mdef);
$definitions[$mcol] = self::sercol($mdef);
} else {
unset($definitions[$mcol]);
}
@ -115,7 +92,7 @@ abstract class CapacitorStorage {
$constraints[] = $def;
}
} else {
$definitions[$col] = self::gencol($def);
$definitions[$col] = self::sercol($def);
}
}
return cl::merge($definitions, $constraints);
@ -238,22 +215,6 @@ abstract class CapacitorStorage {
"class_name" => "varchar",
];
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 _createChannelsSql(): array {
return [
"create table if not exists",
@ -375,10 +336,6 @@ abstract class CapacitorStorage {
$values = func::call([$channel, "getItemValues"], $item, ...$args);
if ($values === [false]) return 0;
if (array_key_exists("item", $values)) {
$item = A::pop($values, "item");
}
$row = cl::merge(
$channel->getSum("item", $item),
$this->serialize($channel, $values));

View File

@ -6,6 +6,7 @@ class _update extends _common {
"prefix" => "?string",
"table" => "?string",
"schema" => "?array",
"cols" => "?array",
"values" => "?array",
"where" => "?array",
"suffix" => "?string",

View File

@ -19,6 +19,10 @@ class MysqlStorage extends CapacitorStorage {
return $this->db;
}
const PRIMARY_KEY_DEFINITION = [
"id_" => "integer primary key auto_increment",
];
protected function tableExists(string $tableName): bool {
$db = $this->db;
$found = $db->get([

View File

@ -9,10 +9,6 @@ class PgsqlStorage extends CapacitorStorage {
const SERDATA_DEFINITION = "text";
const SERSUM_DEFINITION = "varchar(40)";
const SERTS_DEFINITION = "timestamp";
const GENSERIAL_DEFINITION = "serial primary key";
const GENTEXT_DEFINITION = "text";
const GENBOOL_DEFINITION = "boolean";
const GENUUID_DEFINITION = "uuid";
function __construct($pgsql) {
$this->db = Pgsql::with($pgsql);
@ -24,6 +20,10 @@ class PgsqlStorage extends CapacitorStorage {
return $this->db;
}
const PRIMARY_KEY_DEFINITION = [
"id_" => "serial primary key",
];
protected function tableExists(string $tableName): bool {
if (($index = strpos($tableName, ".")) !== false) {
$schemaName = substr($tableName, 0, $index);

View File

@ -9,8 +9,6 @@ use nulib\db\CapacitorStorage;
* Class SqliteStorage
*/
class SqliteStorage extends CapacitorStorage {
const GENSERIAL_DEFINITION = "integer primary key autoincrement";
function __construct($sqlite) {
$this->db = Sqlite::with($sqlite);
}
@ -21,6 +19,10 @@ class SqliteStorage extends CapacitorStorage {
return $this->db;
}
const PRIMARY_KEY_DEFINITION = [
"id_" => "integer primary key autoincrement",
];
protected function tableExists(string $tableName): bool {
$found = $this->db->get([
# depuis la version 3.33.0 le nom officiel de la table est sqlite_schema,
@ -38,6 +40,22 @@ class SqliteStorage extends CapacitorStorage {
return new _sqliteMigration($migrations, $channel->getName());
}
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 {
$sql = parent::_addToChannelsSql($channel);
$sql[0] = "insert or ignore";

View File

@ -117,18 +117,4 @@ class file {
}
return $file;
}
static function string_reader(string $content, ?callable $func=null): MemoryStream {
$file = new MemoryStream();
$file->fwrite($content);
$file->rewind();
if ($func !== null) {
try {
$func($file);
} finally {
$file ->close();
}
}
return $file;
}
}

View File

@ -52,7 +52,6 @@ abstract class AbstractReader implements IReader {
$this->headers = $params["headers"] ?? static::HEADERS;
$this->useHeaders = $params["use_headers"] ?? static::USE_HEADERS;
$this->input = $params["input"] ?? static::INPUT;
$this->skip = $params["skip"] ?? 0;
$this->trim = boolval($params["trim"] ?? static::TRIM);
$this->emptyAsNull = boolval($params["empty_as_null"] ?? static::EMPTY_AS_NULL);
$this->parseNone = boolval($params["parse_none"] ?? static::PARSE_NONE);
@ -68,8 +67,6 @@ abstract class AbstractReader implements IReader {
protected $input;
protected int $skip;
protected bool $trim;
protected bool $emptyAsNull;
@ -84,16 +81,15 @@ abstract class AbstractReader implements IReader {
protected function cookRow(array &$row): bool {
if (!$this->useHeaders) return true;
if ($this->skip > 0) {
$this->skip--;
return false;
}
if ($this->headers === null) {
if ($this->isrc == 0) {
# ligne d'en-tête
if ($this->schema === null) $headers = null;
else $headers = array_keys($this->schema);
if ($headers === null) $headers = $row;
$this->headers = $headers;
$headers = $this->headers;
if ($headers === null) {
if ($this->schema === null) $headers = null;
else $headers = array_keys($this->schema);
if ($headers === null) $headers = $row;
$this->headers = $headers;
}
return false;
}
A::ensure_size($row, count($this->headers));

View File

@ -0,0 +1,124 @@
<?php
namespace nulib\tools;
use nulib\app;
use nulib\app\cli\Application;
use nulib\app\RunFile;
use nulib\ExitError;
use nulib\ext\yaml;
use nulib\os\path;
use nulib\os\proc\Cmd;
use nulib\os\sh;
use nulib\output\msg;
class BgLauncherApp extends Application {
const ACTION_INFOS = 0, ACTION_START = 1, ACTION_STOP = 2;
const ARGS = [
"purpose" => "lancer un script en tâche de fond",
"usage" => "ApplicationClass args...",
"sections" => [
parent::VERBOSITY_SECTION,
],
["-i", "--infos", "name" => "action", "value" => self::ACTION_INFOS,
"help" => "Afficher des informations sur la tâche",
],
["-s", "--start", "name" => "action", "value" => self::ACTION_START,
"help" => "Démarrer la tâche",
],
["-k", "--stop", "name" => "action", "value" => self::ACTION_STOP,
"help" => "Arrêter la tâche",
],
];
protected int $action = self::ACTION_START;
protected ?array $args = null;
static function show_infos(RunFile $runfile, ?int $level=null): void {
msg::print($runfile->getDesc(), $level);
msg::print(yaml::with(["data" => $runfile->read()]), ($level ?? 0) - 1);
}
function main() {
$args = $this->args;
$appClass = $args[0] ?? null;
if ($appClass === null) {
self::die("Vous devez spécifier la classe de l'application");
}
$appClass = $args[0] = str_replace("/", "\\", $appClass);
if (!class_exists($appClass)) {
self::die("$appClass: classe non trouvée");
}
$useRunfile = constant("$appClass::USE_RUNFILE");
if (!$useRunfile) {
self::die("Cette application ne supporte le lancement en tâche de fond");
}
$runfile = app::with($appClass)->getRunfile();
switch ($this->action) {
case self::ACTION_START:
$argc = count($args);
$appClass::_manage_runfile($argc, $args, $runfile);
if ($runfile->warnIfLocked()) self::exit(app::EC_LOCKED);
array_splice($args, 0, 0, [
PHP_BINARY,
path::abspath(NULIB_APP_app_launcher),
]);
app::params_putenv();
self::_start($args, $runfile);
break;
case self::ACTION_STOP:
self::_stop($runfile);
self::show_infos($runfile, -1);
break;
case self::ACTION_INFOS:
self::show_infos($runfile);
break;
}
}
public static function _start(array $args, Runfile $runfile): void {
$pid = pcntl_fork();
if ($pid == -1) {
# parent, impossible de forker
throw new ExitError(app::EC_FORK_PARENT, "Unable to fork");
} elseif (!$pid) {
# child, fork ok
$runfile->wfPrepare($pid);
$outfile = $runfile->getOutfile() ?? "/tmp/NULIB_APP_app_console.out";
$exitcode = app::EC_FORK_CHILD;
try {
# rediriger STDIN, STDOUT et STDERR
fclose(fopen($outfile, "wb")); // vider le fichier
fclose(STDIN); $in = fopen("/dev/null", "rb");
fclose(STDOUT); $out = fopen($outfile, "ab");
fclose(STDERR); $err = fopen($outfile, "ab");
# puis lancer la commande
$cmd = new Cmd($args);
$cmd->addSource("/g/init.env");
$cmd->addRedir("both", $outfile, true);
$cmd->fork_exec($exitcode, false);
sh::_waitpid(-$pid, $exitcode);
} finally {
$runfile->wfReaped($exitcode);
}
}
}
public static function _stop(Runfile $runfile): bool {
$data = $runfile->read();
$pid = $runfile->_getCid($data);
msg::action("stop $pid");
if ($runfile->wfKill($reason)) {
msg::asuccess();
return true;
} else {
msg::afailure($reason);
return false;
}
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace nulib\tools;
use nulib\app;
use nulib\app\cli\Application;
use nulib\output\msg;
use nulib\php\time\DateTime;
use nulib\text\words;
class SteamTrainApp extends Application {
const PROJDIR = __DIR__.'/../..';
const TITLE = "Train à vapeur";
const USE_LOGFILE = true;
const USE_RUNFILE = true;
const USE_RUNLOCK = true;
const ARGS = [
"purpose" => self::TITLE,
"description" => <<<EOT
Cette application peut être utilisée pour tester le lancement des tâches de fond
EOT,
["-c", "--count", "args" => 1,
"help" => "spécifier le nombre d'étapes",
],
["-f", "--force-enabled", "value" => true,
"help" => "lancer la commande même si les tâches planifiées sont désactivées",
],
["-n", "--no-install-signal-handler", "value" => false,
"help" => "ne pas installer le gestionnaire de signaux",
],
];
protected $count = 100;
protected bool $forceEnabled = false;
protected bool $installSignalHandler = true;
function main() {
app::check_bgapplication_enabled($this->forceEnabled);
if ($this->installSignalHandler) app::install_signal_handler();
$count = intval($this->count);
msg::info("Starting train for ".words::q($count, "step#s"));
app::action("Running train...", $count);
for ($i = 1; $i <= $count; $i++) {
msg::print("Tchou-tchou! x $i");
app::step();
sleep(1);
}
msg::info("Stopping train at ".new DateTime());
}
}

39
php/support/copy-templates Executable file
View File

@ -0,0 +1,39 @@
#!/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
declare -A DESTDIRS=(
[template-_bg_launcher.php]=sbin
[template-.launcher.php]=_cli
[template-_wrapper.sh]=_cli
)
declare -A MODES=(
[template-_bg_launcher.php]=+x
[template-.launcher.php]=
[template-_wrapper.sh]=+x
)
projdir=
args=(
"copier les templates dans le projet en cours"
#"usage"
-d:,--projdir: .
)
parse_args "$@"; set -- "${args[@]}"
if [ -n "$projdir" ]; then
cd "$projdir" || die
fi
[ -f composer.json ] || die "$(basename "$(dirname "$(pwd)")"): n'est pas un projet composer"
setx -a templates=ls_files "$MYDIR" "template-*"
for template in "${templates[@]}"; do
destdir="${DESTDIRS[$template]}"
[ -n "$destdir" ] || die "$template: la destination n'est pas configurée"
mode="${MODES[$template]}"
destname="${template#template-}"
tail -n+4 "$MYDIR/$template" >"$destdir/$destname"
[ -n "$mode" ] && chmod "$mode" "$destdir/$destname"
done

View File

@ -1,12 +1,12 @@
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (dans le répertoire cli_config/ par défaut) et modifier les paramètres si nécessaire
# (dans le répertoire _cli/ par défaut) et modifier les paramètres si nécessaire
#-------------------------------------------------------------------------------
<?php
require __DIR__.'/../vendor/autoload.php';
require __DIR__ . '/../vendor/autoload.php';
# Lancer une application en ligne de commande
const NULIB_APP_app_params = [
"projdir" => __DIR__.'/..',
"projdir" => __DIR__ . '/..',
"appcode" => \app\config\bootstrap::APPCODE,
];
require __DIR__.'/../vendor/nulib/base/php/src/app/cli/include-launcher.php';

View File

@ -6,10 +6,10 @@ require __DIR__.'/../vendor/autoload.php';
# Lancer une application en tâche de fond
use nulib\app;
use nulib\cli\BgLauncherApp;
use nulib\tools\BgLauncherApp;
# chemin vers le lanceur PHP
const NULIB_APP_app_launcher = __DIR__.'/../@@CLI@@/.launcher.php';
const NULIB_APP_app_launcher = __DIR__.'/../_cli/.launcher.php';
app::init([
"projdir" => __DIR__.'/..',

View File

@ -1,5 +1,5 @@
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (dans le répertoire cli_config/ par défaut) et modifier les paramétres si nécessaire
# (dans le répertoire _cli/ par défaut) et modifier les paramétres si nécessaire
#-------------------------------------------------------------------------------
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
@ -57,7 +57,7 @@ Vérification des liens..."
for i in *.php*; do
[ -f "$i" ] || continue
name="bin/${i%.*}.php"
dest="../@@CLI@@/_wrapper.sh"
dest="../_cli/_wrapper.sh"
link="../bin/${i%.*}.php"
if [ -L "$link" ]; then
echo "* $name OK"

View File

@ -7,12 +7,6 @@ use nulib\db\Capacitor;
use nulib\db\CapacitorChannel;
class SqliteStorageTest extends TestCase {
static function Txx(...$values): void {
foreach ($values as $value) {
var_export($value);
}
}
function _testChargeStrings(SqliteStorage $storage, ?string $channel) {
$storage->reset($channel);
$storage->charge($channel, "first");
@ -84,7 +78,7 @@ class SqliteStorageTest extends TestCase {
$capacitor->each(["age" => [">", 10]], $setDone, ["++"]);
$capacitor->each(["done" => 0], $setDone, null);
self::Txx(cl::all($capacitor->discharge(false)));
Txx(cl::all($capacitor->discharge(false)));
$capacitor->close();
self::assertTrue(true);
}
@ -139,16 +133,16 @@ class SqliteStorageTest extends TestCase {
$capacitor->charge(["a" => null, "b" => null]);
$capacitor->charge(["a" => "first", "b" => "second"]);
self::Txx("=== all");
Txx("=== all");
/** @var Sqlite $sqlite */
$sqlite = $capacitor->getStorage()->db();
self::Txx(cl::all($sqlite->all([
Txx(cl::all($sqlite->all([
"select",
"from" => $capacitor->getChannel()->getTableName(),
])));
self::Txx("=== each");
Txx("=== each");
$capacitor->each(null, function ($item, $values) {
self::Txx($values);
Txx($values);
});
$capacitor->close();

View File

@ -74,7 +74,7 @@ function build_check_env() {
if template_copy_missing "$PROJDIR/$file"; then
updated=1
setx name=basename -- "$file"
name="${name#.}"; name="${name%.*}"
name="${name#.}"; name="${name%.}"
setx file=dirname -- "$file"
file="$file/$name"
updatedfiles+=("$file")
@ -86,7 +86,7 @@ function build_check_env() {
if template_copy_missing "$file"; then
updated=1
setx name=basename -- "$file"
name="${name#.}"; name="${name%.*}"
name="${name#.}"; name="${name%.}"
setx file=dirname -- "$file"
file="$file/$name"
updatedfiles+=("${file#$PROJDIR/}")

View File

@ -40,31 +40,11 @@ p == 1 {
ac_clean "$conf0"
}
declare -A PHPWRAPPER_DESTDIRS=(
[_bg_launcher.php]=@@SBIN@@
[.launcher.php]=@@CLI@@
[_wrapper.sh]=@@CLI@@
)
declare -A PHPWRAPPER_MODES=(
[_bg_launcher.php]=+x
[.launcher.php]=
[_wrapper.sh]=+x
)
projdir=
install_phpwrappers=auto
args=(
"Mettre à jour le script runphp"
"[path/to/runphp]"
-d:,--projdir:PROJDIR . "\
Copier les fichiers pour un projet de l'université de la Réunion:
- BUILDENV0 et BUILDENV sont fixés à ..env.dist et .env
- les fichiers ..env.dist et .runphp.conf sont créés le cas échéant
- le script build est mis à jour
- les wrappers PHP pour la gestion des tâches de fond sont mis à jour le cas
échéant"
-p,--phpwrappers-install install_phpwrappers=1 "forcer l'installation des wrappers PHP"
--np,--no-phpwrappers-install install_phpwrappers= "ne pas installer les wrappers PHP"
-d:,--projdir:PROJDIR . "Copier les fichiers pour un projet de l'université de la Réunion"
)
parse_args "$@"; set -- "${args[@]}"
@ -113,7 +93,6 @@ else
fi
# (Re)construire le fichier destination
estep "$(relpath "$runphp")"
(
cat "$preamble"
echo
@ -123,81 +102,24 @@ estep "$(relpath "$runphp")"
) >"$runphp"
[ -x "$runphp" ] || chmod +x "$runphp"
eval "$(
vars=(PROJDIR COMPOSERDIR COMPOSERPHAR VENDORDIR BUILDENV0 BUILDENV BUILD_FLAVOUR DIST IMAGENAME)
arrays=(BUILD_IMAGES DISTFILES TEMPLATEFILES VARFILES)
for var in "${vars[@]}"; do eval "$var="; done
for array in "${arrays[@]}"; do eval "$array=()"; done
source "$runphp"
for var in "${vars[@]}"; do echo_setv2 "$var"; done
for array in "${arrays[@]}"; do echo_seta2 "$array"; done
)"
estep "$(relpath "$rundir/Dockerfile.runphp")"
rsync -lpt "$MYDIR/Dockerfile.runphp" "$rundir/"
if [ -n "$projdir" ]; then
if testdiff "$rundir/build" "$MYDIR/build"; then
estep "$(relpath "$rundir/build")"
cp "$MYDIR/build" "$rundir/build"
chmod +x "$rundir/build"
fi
if [ ! -f "$projdir/..env.dist" ]; then
estep "$(relpath "$projdir/..env.dist")"
sed <"$MYDIR/dot-build.env.dist" >"$projdir/..env.dist" '
/^IMAGENAME=/s/=.*\//='"$(basename -- "$projdir")"'\//
'
initial_config=1
fi
if [ ! -f "$projdir/.runphp.conf" ]; then
estep "$(relpath "$projdir/.runphp.conf")"
sed <"$MYDIR/dot-runphp.conf" >"$projdir/.runphp.conf" '
/^RUNPHP=/s/=.*/=sbin\/runphp/
'
fi
sbin_path=sbin
cli_path=cli_config
if [ "$install_phpwrappers" == auto ]; then
if [ ! -f "$PROJDIR/$COMPOSERDIR/composer.json" ]; then
# ce doit être un projet PHP
install_phpwrappers=
elif [ -d "$projdir/cli_config" ]; then
install_phpwrappers=1
sbin_path=sbin
cli_path=cli_config
elif [ -d "$projdir/_cli" ]; then
install_phpwrappers=1
sbin_path=sbin
cli_path=_cli
else
install_phpwrappers=
fi
fi
if [ -n "$install_phpwrappers" ]; then
setx -a phpwrappers=ls_files "$MYDIR" "phpwrapper-*"
for phpwrapper in "${phpwrappers[@]}"; do
destname="${phpwrapper#phpwrapper-}"
destdir="${PHPWRAPPER_DESTDIRS[$destname]}"
[ -n "$destdir" ] || die "$phpwrapper: la destination n'est pas configurée"
mode="${PHPWRAPPER_MODES[$destname]}"
case "$destdir" in
@@SBIN@@) destdir="$PROJDIR/$sbin_path";;
@@CLI@@) destdir="$PROJDIR/$cli_path";;
*) destdir="$PROJDIR/$destdir";;
esac
estep "$(relpath "$destdir/$destname")"
mkdir -p "$destdir"
tail -n+4 "$MYDIR/$phpwrapper" | sed "
s|/@@SBIN@@/|/$sbin_path/|
s|/@@CLI@@/|/$cli_path/|
" >"$destdir/$destname"
[ -n "$mode" ] && chmod "$mode" "$destdir/$destname"
done
fi
fi
[ -n "$initial_config" ]

View File

@ -6,22 +6,9 @@ outil pour gérer les projets PHP
projets dépendants du projet courant
* pver: gestion des versions.
calculer la prochaine version en respectant semver
## scripts de gestion de projet
définir précisément le rôle des scripts
* pdist: créer la branche DIST, basculer dessus, merger MAIN dans DIST
* pmain: initialiser la branche MAIN (si nouveau dépôt), basculer dessus, merger DEVELOP dans MAIN
(s'occupe aussi de la configuration pman.conf)
* pdev: créer la branche DEVELOP, basculer dessus
* pwip: créer une branche WIP, basculer dessus si unique (ou laisser le choix), merger WIP dans DEVELOP
* PEUT-ETRE: pfix: créer une branche HOTFIX, basculer dessus si unique (ou laisser le choix), merger HOTFIX dans MAIN
* prel: faire une release de DEVELOP dans MAIN. à terme, support des branches de hotfix
* il s'agit d'une spécialisation de pmain et/ou pfix pour la gestion des releases
* à terme, gestion en cascade des projets dépendants: release sur un projet downstream, ou synchroniser la version depuis un projet upstream
il faudra supprimer
* pman: fonctionnalités réparties dans les autres scripts spécialisés
* pmer: fonctionnalités réperties dans les autres scripts spécialisés
* 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
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary