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