"dev-wip", "develop" => "dev-develop", ]; const DEFAULT_ALLOW_LINK = false; const DEFAULT_ALLOW_LINKS = [ "wip" => true, "develop" => true, ]; const DEFAULT_CONFIG = [ # cette définition tient compte des valeurs DEFAULT_* ci-dessus "defaults" => [ "wip" => "dev-wip", "develop" => "dev-develop", "master" => [ "version" => "dev-master", "allow_link" => false, ], ], ]; const PROJNAMES = [ # noms de projets particuliers "nulib/php" => "nulib", ]; const DEP_SCHEMA = [ "libname" => ["string", null, "nom de la librairie"], "version" => ["?string", null, "version de la librairie"], "projname" => ["?string", null, "nom du répertoire du projet sur le système de fichier"], "type" => ["?string", null, "type de dépendance"], "url" => ["?string", null, "url de la dépendance"], "allow_link" => ["?bool", null, "peut-on lier vers le projet sur disque?"], "link" => ["?bool", null, "faut-il ajouter l'url dans [repositories]"], "branch" => ["?string", null, "branche de la dépendance dans le projet"], ]; function __construct(string $configFile, ?string $projdir=null, bool $ensureExists=true) { if ($projdir === null) $projdir = dirname($configFile); if ($ensureExists && !file_exists($configFile)) { $message = path::ppath($projdir).": aucune configuration n'a été trouvée"; throw new ValueException($message); } $this->configFile = $configFile; $this->projdir = $projdir; } /** @var string */ protected $configFile; /** @var string */ protected $projdir; /** @var array */ protected $data; protected function load(): array { if ($this->data === null) { $this->data = yaml::load($this->configFile); } 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::with($this->getv($pkey, $default)); } function getBranchDeps(): array { return $this->geta("defaults"); } function getRequires(): array { return $this->geta("require"); } function getBranches(): array { return $this->geta("branch"); } private static $dep_md; private static function dep_md(): Metadata { return md_utils::ensure_md(self::$dep_md, self::DEP_SCHEMA); } /** @var array */ protected $duns; function getDeps(string $branch): array { $dun = A::get($this->duns, $branch); if ($dun !== null) return $dun; $branches = $this->getBranches(); $source = $branch; $valid = array_key_exists($source, $branches); if (!$valid && ($pos = strpos($branch, "/")) !== false) { # pas de définition pour cette branche, essayer avec la branche de base # si la branche est de la forme base/xxx $source = substr($branch, 0, $pos); $valid = array_key_exists($source, $branches); } if (!$valid && array_key_exists("master", $branches)) { # la branche master est utilisée par défaut si elle existe $source = "master"; $valid = true; } if (!$valid) { $dun = [null, null, null]; } else { $projdir = $this->projdir; $branchDeps = $this->getBranchDeps() + self::DEFAULT_DEPS; $defaultDep = null; foreach ($branchDeps as $dbranch => $ddep) { if ($branch == $dbranch) { $defaultDep = $ddep; break; } } if ($defaultDep === null) { foreach ($branchDeps as $dbranch => $ddep) { if (str::starts_with("$dbranch/", $branch)) { $defaultDep = $ddep; break; } } } if ($defaultDep === null) $defaultDep = self::DEFAULT_DEP; self::dep_md()->ensureSchema($defaultDep, ""); $defaultAllowLink = null; foreach (self::DEFAULT_ALLOW_LINKS as $albranch => $alvalue) { if ($branch == $albranch || str::starts_with("$albranch/", $branch)) { $defaultAllowLink = $alvalue; break; } } if ($defaultAllowLink === null) $defaultAllowLink = self::DEFAULT_ALLOW_LINK; # tout d'abord, lister les dépendances $bdeps = []; foreach ($this->getRequires() as $libname => $dep) { if (strpos($libname, "/") === false) continue; if ($dep === false) continue; if ($dep !== null) { self::dep_md()->ensureSchema($dep, $libname); } $bdeps[$libname] = $dep; } foreach ($this->geta("branch.$source") as $libname => $dep) { if ($dep === false) { # une définition par défaut peut être supprimée avec la valeur false A::del($bdeps, $libname); continue; } if ($dep !== null) { self::dep_md()->ensureSchema($dep, $libname); if (!array_key_exists($libname, $bdeps)) $bdeps[$libname] = $dep; elseif ($bdeps[$libname] === null) $bdeps[$libname] = $dep; else A::merge_nn($bdeps[$libname], $dep); } } $deps = []; $isUrls = []; $notFoundUrls = []; foreach ($bdeps as $libname => $dep) { if ($dep === null) { $dep = $defaultDep; $dep["libname"] = $libname; } self::dep_md()->ensureSchema($dep, $libname); $version = $dep["version"]; if ($version === null) $version = $defaultDep["version"]; $projname = $dep["projname"]; if ($projname === null) $projname = A::get(self::PROJNAMES, $libname); if ($projname === null) { $projname = str_replace("/", "-", $libname); } $type = $dep["type"]; if ($type === null) $type = "path"; $url = $dep["url"]; if ($url === null) $url = "../$projname"; $allowLink = $dep["allow_link"]; if ($allowLink === null) $allowLink = $defaultDep["allow_link"]; if ($allowLink === null) $allowLink = $defaultAllowLink; $link = $dep["link"]; if ($link === null) { $isDev = str::starts_with("dev-", $version) || str::ends_with("-dev", $version); $link = $allowLink && $isDev; } if ($link && ( $type !== "path" || !path::is_dir("$projdir/$url", true) )) { $notFoundUrls[] = $url; $link = false; } $vbranch = $version; if (!str::del_prefix($vbranch, "dev-") && !str::del_suffix($vbranch, "-dev")) { $vbranch = null; } A::merge($dep, [ "projname" => $projname, "type" => $type, "url" => $url, "allow_link" => $allowLink, "link" => $link, "branch" => $vbranch, ]); $deps[$libname] = $dep; $isUrls[$url] = true; } $dun = [$deps, $isUrls, $notFoundUrls]; } return $this->duns[$branch] = $dun; } }