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; } }