211 lines
6.5 KiB
PHP
211 lines
6.5 KiB
PHP
<?php
|
|
namespace nur\tools\compctl;
|
|
|
|
use nur\A;
|
|
use nur\b\ValueException;
|
|
use nur\file;
|
|
use nur\json;
|
|
use nur\msg;
|
|
use nur\path;
|
|
use nur\SL;
|
|
use nur\str;
|
|
use nur\yaml;
|
|
|
|
class ComposerFile {
|
|
function __construct(string $composerFile, ?string $projdir=null, bool $ensureExists=true) {
|
|
if ($ensureExists && !file_exists($composerFile)) {
|
|
if ($projdir === null) $projdir = dirname($composerFile);
|
|
$message = path::ppath($projdir).": aucune composeruration n'a été trouvée";
|
|
throw new ValueException($message);
|
|
}
|
|
$this->composerFile = $composerFile;
|
|
}
|
|
|
|
/** @var string */
|
|
protected $composerFile;
|
|
|
|
/** @var array */
|
|
protected $data;
|
|
|
|
protected function load(): array {
|
|
if ($this->data === null) {
|
|
$this->data = json::load($this->composerFile);
|
|
}
|
|
return $this->data;
|
|
}
|
|
|
|
function getv(string $pkey="", $default=null) {
|
|
$this->load();
|
|
return A::pget($this->data, $pkey, $default);
|
|
}
|
|
|
|
function geta(string $pkey="", ?array $default=[]): ?array {
|
|
return A::withn($this->getv($pkey, $default));
|
|
}
|
|
|
|
function getRequires(): array {
|
|
return $this->geta("require");
|
|
}
|
|
|
|
function getRepositories(): array {
|
|
return $this->geta("repositories");
|
|
}
|
|
|
|
/** construire un fichier de configuration à partir du fichier composer */
|
|
function initConfig(string $configFile): ?ConfigFile {
|
|
if (file_exists($configFile)) return null;
|
|
$requires = $this->getRequires();
|
|
$php = A::get($requires, "php", ">=7.4");
|
|
switch ($php) {
|
|
case ">=8.2":
|
|
$composer = [
|
|
"php_min" => "8.2",
|
|
"php_max" => "8.3",
|
|
"image" => "pubdocker.univ-reunion.fr/image/phpbuilder:d12",
|
|
];
|
|
break;
|
|
case ">=7.4":
|
|
$composer = [
|
|
"php_min" => "7.4",
|
|
"php_max" => "8.0",
|
|
"image" => "pubdocker.univ-reunion.fr/image/phpbuilder:d11",
|
|
];
|
|
break;
|
|
case ">=7.3":
|
|
$composer = [
|
|
"php_min" => "7.3",
|
|
"php_max" => "8.0",
|
|
"image" => "pubdocker.univ-reunion.fr/image/phpbuilder:d10",
|
|
];
|
|
break;
|
|
case ">=7.0":
|
|
$composer = [
|
|
"php_min" => "7.0",
|
|
"php_max" => "7.1",
|
|
"image" => "pubdocker.univ-reunion.fr/image/phpbuilder:d9",
|
|
];
|
|
break;
|
|
default:
|
|
msg::warning("$php: impossible de calculer la valeur de \$composer, choix du support de PHP 7.4");
|
|
$composer = [
|
|
"php_min" => "7.4",
|
|
"php_max" => "8.0",
|
|
"image" => "pubdocker.univ-reunion.fr/image/phpbuilder:d11",
|
|
];
|
|
break;
|
|
}
|
|
$defaults = ConfigFile::DEFAULT_CONFIG["defaults"];
|
|
$require = null;
|
|
foreach ($requires as $libname => $version) {
|
|
$isNur = str::starts_with("nur/", $libname);
|
|
$isLib = str::starts_with("lib/", $libname);
|
|
if (!$isNur && !$isLib) continue;
|
|
if (str::starts_with("dev-", $version)
|
|
|| str::ends_with("-dev", $version)) {
|
|
# version de développement, laisser se calculer les valeurs par défaut
|
|
$require[$libname] = null;
|
|
} else {
|
|
$require[$libname] = $version;
|
|
}
|
|
}
|
|
$branches = array_fill_keys(array_keys($defaults), null);
|
|
$config = [
|
|
"composer" => $composer,
|
|
#"defaults" => $defaults,
|
|
"require" => $require,
|
|
"branch" => $branches,
|
|
];
|
|
$contents = yaml::with($config);
|
|
# pour la joliesse, enlever les ': null'
|
|
$contents = preg_replace('/: null$/m', ":", $contents);
|
|
|
|
$writer = file::with($configFile)->getWriter();
|
|
$writer->pnl("# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8");
|
|
$writer->putContents($contents);
|
|
return new ConfigFile($configFile);
|
|
}
|
|
|
|
function computeComposer(ConfigFile $config, string $branch): array {
|
|
$data = $orig = $this->load();
|
|
|
|
[$deps, $isUrls, $notFoundUrls,
|
|
] = $config->getDeps($branch);
|
|
if ($deps === null) {
|
|
msg::warning("$branch: aucune définition trouvée pour cette branche");
|
|
return [false, $orig];
|
|
}
|
|
foreach ($notFoundUrls as $url) {
|
|
msg::warning("$url: project not found. not updating repositories");
|
|
}
|
|
|
|
# nettoyer les chemins pour chacune des dépendances de la config
|
|
$crequires = A::get($data, "require", []);
|
|
$crepositories = A::get($data, "repositories");
|
|
if ($crepositories === null) {
|
|
$crepositories = [[
|
|
"type" => "composer",
|
|
"url" => "https://repos.univ-reunion.fr/composer",
|
|
]];
|
|
}
|
|
foreach ($crepositories as $key => $crepository) {
|
|
if (A::get($crepository, "type") !== "path") continue;
|
|
$url = A::get($crepository, "url");
|
|
if (A::get($isUrls, $url)) {
|
|
unset($crepositories[$key]);
|
|
continue;
|
|
}
|
|
# si un projet nur/ ou lib/ se trouve dans require, le prendre en compte
|
|
# en d'autres termes, on nettoie les chemins qui n'ont plus de correspondance...
|
|
$projname = basename($url);
|
|
$libname = null;
|
|
if (str::del_prefix($projname, "nur-")) {
|
|
$libname = "nur/$projname";
|
|
} elseif (str::del_prefix($projname, "lib-")) {
|
|
$libname = "lib/$projname";
|
|
}
|
|
if ($libname !== null && array_key_exists($libname, $crequires)) {
|
|
unset($crepositories[$key]);
|
|
}
|
|
}
|
|
$data["repositories"] = $crepositories;
|
|
# puis recalculer la liste des chemins
|
|
$crepositories = [];
|
|
foreach ($deps as $dep) {
|
|
if ($dep["link"]) {
|
|
$crepositories[] = [
|
|
"type" => $dep["type"],
|
|
"url" => $dep["url"],
|
|
];
|
|
}
|
|
}
|
|
$data["repositories"] = SL::merge($crepositories, $data["repositories"]);
|
|
# nettoyer les dépendances pour chacune des dépendances de la config
|
|
foreach ($crequires as $libname => $version) {
|
|
if (array_key_exists($libname, $deps)) {
|
|
unset($crequires[$libname]);
|
|
}
|
|
}
|
|
$data["require"] = $crequires;
|
|
# puis installer les dépendances de la config
|
|
$crequires = [];
|
|
foreach ($deps as $dep) {
|
|
$crequires[$dep["libname"]] = $dep["version"];
|
|
}
|
|
$data["require"] = SL::merge($crequires, $data["require"]);
|
|
# retourner le nouveau contenu (qu'il faudra sérialiser)
|
|
return [$data != $orig, $data];
|
|
}
|
|
|
|
function sync(ConfigFile $config, string $branch, bool $inplace=false): bool {
|
|
[$modified, $json] = $this->computeComposer($config, $branch);
|
|
$contents = json::with($json, json::INDENT_TABS);
|
|
if ($inplace) {
|
|
if ($modified) file::with($this->composerFile)->putContents($contents);
|
|
else msg::info("Aucune modifications effectuée");
|
|
} else {
|
|
if ($contents !== null) echo "$contents\n";
|
|
}
|
|
return $modified;
|
|
}
|
|
}
|