ajout src_glue

This commit is contained in:
Jephté Clain 2024-11-29 08:41:02 +04:00
parent 73c0cb4c13
commit 5f2547c665
12 changed files with 20 additions and 458 deletions

View File

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

View File

@ -19,7 +19,6 @@
},
"require-dev": {
"nulib/php": "^7.4-dev",
"nulib/yaml": "^7.4-dev",
"nulib/spout": "^7.4-dev",
"nulib/phpss": "^7.4-dev",
"nulib/tests": "^7.4",
@ -53,6 +52,7 @@
},
"autoload": {
"psr-4": {
"nulib\\": "src_glue",
"nur\\sery\\wip\\": "src",
"nur\\sery\\": "src_app",
"nur\\": "nur_src"

58
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fd786c1eb69e14f16916905711daf8ca",
"content-hash": "ff7940a16992c5de7cd4078864ed2e95",
"packages": [],
"packages-dev": [
{
@ -510,10 +510,12 @@
"source": {
"type": "git",
"url": "https://git.univ-reunion.fr/sda-php/nulib.git",
"reference": "325391d60c2ed3a6ead71992d98aa2ce205bd293"
"reference": "3958b8f11d16d7a4c17feb415b9158425608112a"
},
"require": {
"php": "^7.4"
"ext-json": "*",
"php": "^7.4",
"symfony/yaml": "^5.0"
},
"require-dev": {
"ext-curl": "*",
@ -545,7 +547,7 @@
}
],
"description": "fonctions et classes essentielles",
"time": "2024-11-28T16:58:43+00:00"
"time": "2024-11-29T04:40:10+00:00"
},
{
"name": "nulib/phpss",
@ -595,7 +597,7 @@
"source": {
"type": "git",
"url": "https://git.univ-reunion.fr/sda-php/nulib-spout.git",
"reference": "9f2bc810e487949528045676fe36ba64b96144d1"
"reference": "d416e6799b9716d254e0cb7b31724e9e2f75d47d"
},
"require": {
"ext-dom": "*",
@ -641,7 +643,7 @@
}
],
"description": "wrapper pour openspout/openspout",
"time": "2024-11-28T16:39:08+00:00"
"time": "2024-11-28T17:36:37+00:00"
},
{
"name": "nulib/tests",
@ -675,49 +677,6 @@
"description": "fonctions et classes pour les tests",
"time": "2024-03-26T10:56:17+00:00"
},
{
"name": "nulib/yaml",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://git.univ-reunion.fr/sda-php/nulib-yaml.git",
"reference": "b53fa6512e8ce20f6afe42a7ca6caf20da220f76"
},
"require": {
"ext-json": "*",
"nulib/php": "^7.4-dev",
"php": "^7.4",
"symfony/yaml": "^5.0"
},
"require-dev": {
"nulib/tests": "^7.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "7.4.x-dev",
"dev-php82": "8.2.x-dev"
}
},
"autoload": {
"psr-4": {
"nulib\\ext\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"nulib\\ext\\": "tests"
}
},
"authors": [
{
"name": "Jephte Clain",
"email": "Jephte.Clain@univ-reunion.fr"
}
],
"description": "Support YAML et JSON",
"time": "2024-11-28T16:04:34+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.4",
@ -2893,7 +2852,6 @@
"minimum-stability": "stable",
"stability-flags": {
"nulib/php": 20,
"nulib/yaml": 20,
"nulib/spout": 20,
"nulib/phpss": 20
},

View File

@ -1,29 +0,0 @@
<?php
# script à inclure pour implémenter .launcher.php
# les constantes suivantes doivent être définies AVANT de chager ce script:
# - NULIB_APP_app_params : paramètres du projet
use nur\sery\app;
use nulib\os\path;
if ($argc <= 1) die("invalid arguments");
app::init(NULIB_APP_app_params);
$app = $argv[1];
array_splice($argv, 0, 1); $argc--;
if (class_exists($app)) {
# la configuration est celle actuellement chargée
$app::run();
} elseif (is_executable($app)) {
# la configuration est passée par une variable d'environnement
app::params_putenv();
pcntl_exec($app, array_slice($argv, 1));
} else {
# la configuration est celle actuellement chargée
$name = preg_replace('/\.php$/', "", path::basename($app));
app::init([
"name" => $name,
]);
require $app;
}

View File

@ -1,124 +0,0 @@
<?php
namespace nur\sery\tools;
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;
use nur\sery\app;
use nur\sery\app\cli\Application;
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

@ -1,53 +0,0 @@
<?php
namespace nur\sery\tools;
use nulib\output\msg;
use nulib\php\time\DateTime;
use nulib\text\words;
use nur\sery\app;
use nur\sery\app\cli\Application;
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());
}
}

5
src_glue/app.php Normal file
View File

@ -0,0 +1,5 @@
<?php
namespace nulib;
class app extends \nur\sery\app {
}

View File

@ -0,0 +1,5 @@
<?php
namespace nulib\app\cli;
abstract class Application extends \nur\sery\app\cli\Application {
}

View File

@ -1,39 +0,0 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source /etc/nulib.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 +0,0 @@
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (dans le répertoire _cli/ par défaut) et modifier les paramètres si nécessaire
#-------------------------------------------------------------------------------
<?php
require __DIR__ . '/../vendor/autoload.php';
# Lancer une application en ligne de commande
const NULIB_APP_app_params = [
"projdir" => __DIR__ . '/..',
"appcode" => \app\config\bootstrap::APPCODE,
];
require __DIR__.'/../vendor/nur/ture/src_app/app/cli/include-launcher.php';

View File

@ -1,18 +0,0 @@
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (dans le répertoire sbin/ par défaut) et modifier les paramètres si nécessaire
#-------------------------------------------------------------------------------
<?php
require __DIR__.'/../vendor/autoload.php';
# Lancer une application en tâche de fond
use nulib\tools\BgLauncherApp;
use nur\sery\app;
# chemin vers le lanceur PHP
const NULIB_APP_app_launcher = __DIR__.'/../_cli/.launcher.php';
app::init([
"projdir" => __DIR__.'/..',
"appcode" => \app\config\bootstrap::APPCODE,
]);
BgLauncherApp::run();

View File

@ -1,132 +0,0 @@
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (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
# S'assurer que le script PHP est lancé avec l'utilisateur www-data
# Tous les chemins suivants sont relatifs au répertoire qui contient ce script
# Chemin relatif de la racine du projet
PROJPATH=..
# Chemin relatif vers le lanceur PHP
LAUNCHERPATH=.launcher.php
# Chemin relatif des scripts PHP wrappés
WRAPPEDPATH=
# Nom du service dans docker-compose.yml utilisé pour lancer les commandes
COMPOSE_SERVICE=web
###############################################################################
case "${RUNPHP_MODE:-auto}" in
auto)
RUNPHP_MODE=
[ -f /.dockerenv ] && RUNPHP_MODE=docker
[ -z "$RUNPHP_MODE" ] &&
[ -f /proc/self/mountinfo ] &&
grep -q ' /docker/' /proc/self/mountinfo &&
RUNPHP_MODE=docker
[ -z "$RUNPHP_MODE" ] &&
[ -f /proc/1/cgroup ] &&
grep -q ':/docker/' /proc/1/cgroup &&
RUNPHP_MODE=docker
[ -n "$RUNPHP_MODE" ] || RUNPHP_MODE=host
;;
docker) RUNPHP_MODE=docker;;
host) RUNPHP_MODE=host;;
direct) RUNPHP_MODE=direct;;
*) RUNPHP_MODE=host;;
esac
MYDIR="$(dirname -- "$0")"
MYNAME="$(basename -- "$0")"
if [ ! -L "$0" ]; then
echo "\
$0
Ce script doit être lancé en tant que lien symbolique avec un nom de la forme
'monscript.php' et lance le script PHP du même nom situé dans le même répertoire
avec l'utilisateur www-data"
if [ "$RUNPHP_MODE" == host -o "$RUNPHP_MODE" == direct ]; then
echo "\
----------------------------------------
Vérification des liens..."
cd "$MYDIR"
for i in *.php*; do
[ -f "$i" ] || continue
name="bin/${i%.*}.php"
dest="../_cli/_wrapper.sh"
link="../bin/${i%.*}.php"
if [ -L "$link" ]; then
echo "* $name OK"
elif [ -e "$link" ]; then
echo "* $name KO (not a link)"
else
echo "* $name NEW"
ln -s "$dest" "$link" || exit 1
fi
done
fi
exit 0
fi
MYTRUESELF="$(readlink -f "$0")"
MYTRUEDIR="$(dirname -- "$MYTRUESELF")"
PROJDIR="$(cd "$MYTRUEDIR${PROJPATH:+/$PROJPATH}"; pwd)"
if [ "$RUNPHP_MODE" == host ]; then
args=(
docker compose run
${RUNPHP_BUILD:+--build}
--rm
)
cwd="$(pwd)"
mounted=
if [ "$PROJDIR" == "$HOME" -o "${PROJDIR#$HOME/}" != "$PROJDIR" ]; then
# monter HOME
args+=(-v "$HOME:$HOME")
[ "${cwd#$HOME/}" != "$cwd" ] && mounted=1
else
# monter uniquement le répertoire du projet
args+=(-v "$PROJDIR:$PROJDIR")
[ "${cwd#$PROJDIR/}" != "$cwd" ] && mounted=1
fi
if [ -z "$mounted" ]; then
echo "Impossible de mapper le répertoire courant avec les montages du container"
exit 1
fi
args+=(
--workdir "$cwd"
"$COMPOSE_SERVICE"
exec "$MYNAME"
"$@"
)
cd "$PROJDIR"
exec "${args[@]}"
fi
launcher="$MYTRUEDIR/$LAUNCHERPATH"
class="$MYTRUEDIR${WRAPPEDPATH:+/$WRAPPEDPATH}/${MYNAME%.php}.phpc"
script="$MYTRUEDIR${WRAPPEDPATH:+/$WRAPPEDPATH}/${MYNAME%.php}.php"
[ -f /g/init.env ] && source /g/init.env
www_data="${DEVUSER_USERENT%%:*}"
[ -n "$www_data" ] || www_data=www-data
cmd=(php "$launcher")
[ -n "$MEMPROF_PROFILE" ] && cmd+=(-dextension=memprof.so)
if [ -f "$class" ]; then
cmd+=("$(<"$class")")
else
cmd+=("$script")
fi
cmd+=("$@")
if [ "$(id -u)" -eq 0 ]; then
su-exec "$www_data" "${cmd[@]}"
else
exec "${cmd[@]}"
fi