#!/usr/bin/env php * * @category CheckPkgist * @package FedoraClient * * @author Remi Collet * @copyright 2014-2024 Remi Collet * @license http://www.gnu.org/licenses/lgpl-2.1.txt LGPL License 2.1 or (at your option) any later version * @link https://github.com/remicollet/remirepo/tree/master/tools/checkpkgist */ require_once 'Cache/Lite.php'; if (!ini_get('date.timezone')) { ini_set('date.timezone', 'Europe/Paris'); } define ('VERSION', '1.1.0-dev'); class PkgClient { const URL = 'https://packagist.org/'; protected $cache; function __construct () { $dir = "/tmp/pkgist-".posix_getlogin()."/"; @mkdir($dir); $this->cache = new Cache_Lite( array( 'memoryCaching' => true, 'cacheDir' => $dir, 'lifeTime' => 1800, 'automaticSerialization' => true ) ); } function getPackage($name) { $url = self::URL . "p/$name.json"; $rep = $this->cache->get(__METHOD__, $url); if (!$rep) { $rep = @file_get_contents($url); $this->cache->save($rep, __METHOD__, $url); } if ($rep) { $rep =json_decode($rep, true); if (isset($rep['packages'][$name])) { // Higher version first uksort($rep['packages'][$name], function($a, $b) { return version_compare($b, $a); }); } return $rep; } return false; } } function getMax($name, $rpm) { static $vers = NULL; global $pkgs; if (is_null($vers)) { if ($vers = file_get_contents(__DIR__."/multiver.json")) { $vers = json_decode($vers, true, 5); } else { $vers = []; } } $rpms = array_keys($pkgs, $name); $crt = 0; $max = 9999; if (isset($vers[$rpm])) { $crt = $vers[$rpm]; $max = $crt+1; } else if (preg_match('/[0-9]+$/', $rpm, $reg)) { // This already a versionned name $crt = intval($reg[0]); $max = $crt+1; } foreach($rpms as $alt) { if ($alt != $rpm && preg_match('/[0-9]+$/', $alt, $reg)) { $ver = intval($reg[0]); if ($ver>$crt && $ver<$max) { $max = $ver; } } } return $max; } function displayName($rpm, $pkg, $len=50) { $len -= strlen($rpm) + 3; if (strlen($pkg) > $len) { $pkg = '.' . substr($pkg, -($len-1)); } return "$rpm ($pkg)"; } function run($name, $rpm) { global $quiet, $verb, $client; $name = strtolower($name); $len = 50; $limit = getMax($name, $rpm); if (in_array($name, ['znerol/php-stringprep', 'psr/http-message-implementation'])) { return; } if (!strpos($name, '/')) { // e.g. ext-foo return; } list($owner, $library) = explode('/', $name, 2); if (in_array($owner, ['horde', 'kolab'])) { return; } if (!$quiet) { printf(" %-80s\r", $rpm); } $rpminfo=rpmdbinfo($rpm); if ($rpminfo) { $rpminfo = $rpminfo[0]; $rpmmainver = $rpminfo['Version']; } else { if ($quiet) { return; } $rpmmainver = "n/a"; $rpminfo['Providename'] = ["php-composer($name)"]; $rpminfo['Provideversion'] =[$rpmmainver]; } $cpt = 0; foreach($rpminfo['Providename'] as $i => $n) { if (preg_match('/^php-composer\((.*)\)/', $n, $res)) { $name = $res[1]; } else { unset($rpminfo['Providename'][$i]); continue; } if (strpos($name, '-implementation') || strpos($name, '-api') || strpos($name, '/zend')) { unset($rpminfo['Providename'][$i]); continue; } $cpt++; } if (!$cpt) { $rpminfo['Providename'] = ["php-composer($name)"]; $rpminfo['Provideversion'] =[$rpmmainver]; } foreach($rpminfo['Providename'] as $i => $n) { if (preg_match('/php-composer\((.*)\)/', $n, $res)) { $rpmver = $rpminfo['Provideversion'][$i]; $name = $res[1]; } $pkgs = $client->getPackage($name); if ($pkgs && isset($pkgs['packages'][$name])) { $maxver = ""; $maxdat = false; $display = false; foreach ($pkgs['packages'][$name] as $pkver => $pkg) { if (preg_match('/^v[\.0-9]*$/', $pkver)) { $pkver = substr($pkver, 1); } if (strpos($pkver, 'dev') !== false) { continue; } $date = new DateTime($pkg['time']??'now'); if (version_compare($pkver, $maxver, 'gt')) { $maxver = $pkver; $maxdat = $date; } if (version_compare($pkver, $limit, 'ge')) { continue; } if (version_compare($pkver, $rpmver, 'gt')) { $diff = $date->diff(new DateTime("now")); $rpm2 = $rpm; if ($diff->days <2) { $note = "(Just released)"; $rpm2 = substr($rpm . ' ' . str_repeat('.', $len), 0, $len); } else if ($diff->days <20) { $note = $diff->format("(%a days)"); } else { $note = ""; } //print_r($pkg); printf(" %-{$len}.{$len}s %15s %15s %15s %s\n", ($verb ? displayName($rpm2, $name, $len) : $rpm2), $rpmver, $pkver, $date->format("Y-m-d"), $note); if ($pkg['source']['type']=='git' && $verb) { printf("\tURL: %s\n\tHash: %s\n", ($pkg['source']['url']?:'unkown'), ($pkg['source']['reference']?:'unkown')); } $display = true; if (!$verb) { break; } } else if (version_compare($pkver, $rpmver, 'eq') && $verb && !$display) { printf(" %-{$len}.{$len}s %15s %15s %15s\n", displayName($rpm, $name, $len), $rpmver, $pkver, $date->format("Y-m-d")); $display = true; if (!$verb) { break; } } } if ($verb && !$display) { printf(" %-{$len}.{$len}s %15s %15s %15s\n", displayName($rpm, $name, $len), $rpmver, ($maxver ?: 'unkown'), ($maxdat ? $date->format("Y-m-d") : '')); } } else if (!$quiet) { printf(" %-{$len}.{$len}s %15s %15s\n", displayName($rpm, $name, $len), $rpmver, "Not found!"); } } } printf("\nCheckPkgist version %s by Remi Collet.\n\n", VERSION); if (!extension_loaded('rpminfo')) { die("rpminfo extension is missing\n"); } rpmaddtag(RPMTAG_PROVIDES); rpmaddtag(RPMTAG_PROVIDEVERSION); if (in_array('-h', $_SERVER['argv']) || in_array('--help', $_SERVER['argv'])) { echo << $pkg) { if (isset($pkgs[$rpm])) { unset($pkg2[$rpm]); $change = true; } else { $pkgs[$rpm] = $pkg2[$rpm]; } } if ($change) { if (file_put_contents(__DIR__."/checkpkgist.json", json_encode($pkg2, JSON_PRETTY_PRINT))) { printf("Configuration file changes saved\n"); } } if ($sort) { natcasesort($pkgs); } printf(" %-50s %15s %15s %15s\n", "Name", "Version", "Upstream", "Date"); $tmp = array(); for ($i=1 ; $i<$_SERVER['argc'] ; $i++) { if (is_dir($rpm = $_SERVER['argv'][$i])) { $rpm = basename(realpath($_SERVER['argv'][$i])); } if (isset($pkgs[$rpm])) { $tmp[$rpm] = $pkgs[$rpm]; } } if (count($tmp)) { $verb = true; $scan = $tmp; } else { $scan = $pkgs; } foreach ($scan as $rpm => $name) { run($name, $rpm); } echo str_repeat(' ', 80)."\n";