Un script pour s'inscrire (watch) à tous les projets de git.spip.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
7.6 KiB

#!/usr/bin/php
<?php
define('_DIR_TMP', getcwd());
define('_DIR_RESTREINT', 'ecrire/');
define('_DIR_RACINE', '');
define('_SPIP_CHMOD', 0777);
$url_orgs = [
'https://git.spip.net/spip-contrib-squelettes',
'https://git.spip.net/spip-contrib-extensions',
'https://git.spip.net/spip-contrib-themes',
'https://git.spip.net/spip-contrib-outils',
'https://git.spip.net/spip-galaxie',
'https://git.spip.net/spip'
];
$endpoint = gitea_endpoint_from_url($url_orgs[0]);
// 1/ lire le token en paramètre
$args = $argv;
array_shift($args); // inutile : le nom du script
if(!$token = reset($args)){
echo "\nindiquez votre token secret en paramètre\n\n";
die();
}
// 2/ lire les repos déjà souscrits
$subscribed = array();
$total_subscribed = 0;
$res = gitea_json_api_call($endpoint, 'user/subscriptions?token='.$token);
foreach ($res as $item) {
list($org,$name) = explode('/',$item['full_name']);
$subscribed[$org][] = $name;
$total_subscribed++;
}
echo "\n# watching $total_subscribed repositories\n";
// 3/ subscribe repos
$total_repos = 0;
$total_added = 0;
foreach ($url_orgs as $url_org) {
$added = 0;
$repos = gitea_lister_repositories($url_org, time() - 10 * 60);
$total = count($repos);
$total_repos += $total;
$org = gitea_organisation_from_url($url_org);
echo "\n# $total repositories dans $org";
// extraire les repos déjà souscrits (pour limiter le nombre d'appels à l'API)
$repos_names = array_column($repos,'name');
$diff = array_diff($repos_names,$subscribed[$org]);
echo "\n# ".count($diff).' repositories non souscrits';
foreach ($diff as $repo) {
$method = "repos/$org/$repo/subscription?token=$token";
$res = gitea_json_api_call($endpoint, $method, 'PUT');
if (!isset($res['errors']) && isset($res['subscribed']) && $res['subscribed']) {
$added++;
echo "\nsouscription : $org/$repo";
} else {
gitea_fail("echec de la souscription : $org/$repo", print_r($res, 1));
}
}
echo "\n# $added repositories ajoutés\n\n";
}
echo "\n$total_repos repositories au total\n\n";
/**
* Lister les repositories d'une organisation
* @param string $url_organisation
* @param int $last_modified_time
* @return array
*/
function gitea_lister_repositories($url_organisation, $last_modified_time = null) {
$endpoint = gitea_endpoint_from_url($url_organisation);
$org = gitea_organisation_from_url($url_organisation);
$method = "orgs/{$org}/repos";
$res = gitea_json_api_call($endpoint, $method, 'GET', $last_modified_time);
$repositories = [];
if ($res) {
foreach ($res as $k => $row) {
if ($k === 'message' and is_string($row)) {
gitea_fail("Echec API Gitea", implode("\n", [$url_organisation, "API Call $endpoint $method", $row, json_encode($res)]));
}
if (is_array($row) and !empty($row['clone_url'])) {
$repositories[$row['clone_url']] = [
'name' => $row['name'],
'full_name' => $row['full_name'],
'url' => $row['clone_url'],
'url_ssh' => $row['ssh_url'],
'empty' => $row['empty'],
'last_modified' => strtotime($row['updated_at'])
];
}
}
}
return $repositories;
}
/**
* Appel de l'API JSON avec cache si possible
* (mais par defaut pas de cache)
*
* @param $endpoint : API endpoint
* @param $method : API method
* @param $request : HTTP request (GET, PUT, ...)
* @param null $last_modified_time
* @return false|mixed|string
*/
function gitea_json_api_call($endpoint, $method, $request = 'GET', $last_modified_time = null) {
$dir_cache = sous_repertoire(_DIR_TMP, 'cache');
$dir_cache = sous_repertoire($dir_cache, 'gitea');
$file_cache = $dir_cache . "api-" . md5("json_api_call:$endpoint:$method") . ".json";
if ($request == 'GET' && !is_null($last_modified_time)
and file_exists($file_cache)
and filemtime($file_cache) > $last_modified_time
and $json = file_get_contents($file_cache)
and ($json = json_decode($json, true)) !== false) {
return $json;
}
$url = $endpoint . $method;
//$command = "curl --silent -X $request -L '$url' -H 'accept: application/json'";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
if ($request == 'PUT') {
curl_setopt($curl, CURLOPT_PUT, true);
}
$output = [];
try {
//exec($command, $output);
$output = curl_exec($curl);
curl_close($curl);
//$output = trim(implode("\n", $output));
$json = json_decode($output, true);
if ($json !== false and !is_null($json)) {
file_put_contents($file_cache, json_encode($json));
return $json;
}
else {
gitea_fail("Echec call API $url");
}
} catch (Exception $e) {
echo 'Repo en erreur : ', $e->getMessage(), "\n";
return false;
}
}
function gitea_endpoint_from_url($url){
$url = explode('://', $url, 2);
$host = explode("/", end($url), 2);
$endpoint = $url[0] . "://" . $host[0] . "/api/v1/";
return $endpoint;
}
function gitea_repository_from_url($url){
$url = explode('://', $url, 2);
$path = explode("/", end($url), 2);
$path = end($path);
$repository = preg_replace(",\.git$,", "", $path);
return $repository;
}
function gitea_organisation_from_url($url){
$repository = gitea_repository_from_url($url);
$repository = explode('/', $repository);
$organisation = reset($repository);
return $organisation;
}
/**
* Echec sur erreur : on echoue en lançant une exception
* @param $sujet
* @param $corps
* @throws Exception
*/
function gitea_fail($sujet, $corps=''){
echo "\n$sujet\n".($corps ? rtrim($corps) . "\n" : "")."\n";
//die();
throw new Exception($sujet);
}
/**
* Crée un sous répertoire
*
* Retourne `$base/${subdir}/` si le sous-repertoire peut être crée
*
* @example
* ```
* sous_repertoire(_DIR_CACHE, 'demo');
* sous_repertoire(_DIR_CACHE . '/demo');
* ```
*
* @param string $base
* - Chemin du répertoire parent (avec $subdir)
* - sinon chemin du répertoire à créer
* @param string $subdir
* - Nom du sous répertoire à créer,
* - non transmis, `$subdir` vaut alors ce qui suit le dernier `/` dans `$base`
* @param bool $nobase
* true pour ne pas avoir le chemin du parent `$base/` dans le retour
* @param bool $tantpis
* true pour ne pas raler en cas de non création du répertoire
* @return string
* Chemin du répertoire créé.
**/
function sous_repertoire($base, $subdir = '', $nobase = false, $tantpis = false) {
static $dirs = array();
$base = str_replace("//", "/", $base);
# suppr le dernier caractere si c'est un /
$base = rtrim($base, '/');
if (!strlen($subdir)) {
$n = strrpos($base, "/");
if ($n === false) {
return $nobase ? '' : ($base . '/');
}
$subdir = substr($base, $n + 1);
$base = substr($base, 0, $n + 1);
} else {
$base .= '/';
$subdir = str_replace("/", "", $subdir);
}
$baseaff = $nobase ? '' : $base;
if (isset($dirs[$base . $subdir])) {
return $baseaff . $dirs[$base . $subdir];
}
$path = $base . $subdir; # $path = 'IMG/distant/pdf' ou 'IMG/distant_pdf'
if (file_exists("$path/.ok")) {
return $baseaff . ($dirs[$base . $subdir] = "$subdir/");
}
@mkdir($path, _SPIP_CHMOD);
@chmod($path, _SPIP_CHMOD);
if (is_dir($path) && is_writable($path)) {
@touch("$path/.ok");
spip_log("creation $base$subdir/");
return $baseaff . ($dirs[$base . $subdir] = "$subdir/");
}
// en cas d'echec c'est peut etre tout simplement que le disque est plein :
// l'inode du fichier dir_test existe, mais impossible d'y mettre du contenu
spip_log("echec creation $base${subdir}");
if ($tantpis) {
return '';
}
if (!_DIR_RESTREINT) {
$base = preg_replace(',^' . _DIR_RACINE . ',', '', $base);
}
$base .= $subdir;
//raler_fichier($base . '/.ok');
exit("echec creation $base". '/.ok');
}
function spip_log($message, $logfile='spip') {
}