Browse Source

Un script pour faire un mirroir de tous les repos de git.spip.net

pull/2/head
Cerdic 1 year ago
commit
e7cda4181e
  1. 282
      mirror.php

282
mirror.php

@ -0,0 +1,282 @@
#!/usr/bin/php
<?php
// quelques constantes pour faire marcher les fonctions copie-colle de SPIP ou du plugin debardeur
define('_SPIP_CHMOD', 0777);
define('_DIR_DEBARDEUR_TMP', getcwd());
define('_DIR_RESTREINT', 'ecrire/');
define('_DIR_RACINE', '');
$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'
];
$errors = [];
$updated = [];
$empty = [];
foreach ($url_orgs as $url_org) {
$repos = debardeur_connecteur_gitea_lister_repositories($url_org, time() - 10 * 60);
$total = count($repos);
echo "\n# $total repositories dans $url_org\n";
$nb = 0;
foreach ($repos as $repo) {
$nb++;
$dir = $repo['full_name'];
$url = $repo['url'];
$last_modified = $repo['last_modified'];
echo "$nb/$total. $url";
if ($repo['empty']) {
$empty[] = $url;
echo " => Vide\n";
}
else {
$gitindex = "$dir/.git/index";
if (!is_dir($dir)
or !file_exists($gitindex)
or !$t = filemtime($gitindex)
or $t < $last_modified) {
$updated[] = $url;
if (file_exists("$dir/.ignore")) {
$errors[] = $url;
}
else {
$cmd = "checkout.php -bmaster $url $dir";
echo "\n$cmd\n";
passthru($cmd);
echo "\n";
if (!file_exists($gitindex)) {
$errors[] = $url;
}
}
}
else {
echo " => OK\n";
}
}
}
}
if ($empty) {
$nb_empty = count($empty);
echo "\n$nb_empty Repositories vides\n" . '- ' . implode("\n- ", $empty);
}
if ($updated) {
$nb_updated = count($updated);
echo "\n$nb_updated Repositories mis a jour\n" . '- ' . implode("\n- ", $updated);
}
if ($errors) {
$nb_errors = count($errors);
debardeur_fail("$nb_errors Repositories en erreur", '- ' . implode("\n- ", $errors));
}
echo "\n";
/**
* Lister les repositories d'une organisation
* @param string $url_organisation
* @param int $last_modified_time
* @return array
*/
function debardeur_connecteur_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 = debardeur_json_api_call('gitea', $endpoint, $method, $last_modified_time);
$repositories = [];
if ($res) {
foreach ($res as $k => $row) {
if ($k === 'message' and is_string($row)) {
debardeur_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'],
'empty' => $row['empty'],
'last_modified' => strtotime($row['updated_at'])
];
}
}
}
return $repositories;
}
/**
* Appel d'une l'API JSON en get (type gitea/github) avec cache si possible
* (mais par defaut pas de cache)
*
* @param $endpoint
* @param $method
* @param null $last_modified_time
* @return false|mixed|string
*/
function debardeur_json_api_call($type, $endpoint, $method, $last_modified_time = null) {
$dir_cache = sous_repertoire(_DIR_DEBARDEUR_TMP, 'cache');
$dir_cache = sous_repertoire($dir_cache, $type);
$file_cache = $dir_cache . "api-" . md5("debardeur_json_api_call:$endpoint:$method") . ".json";
if (!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 -L '$url' -H 'accept: application/json'";
$output = [];
exec($command, $output);
$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 {
spip_log("Echec call API $url", 'debardeur_call_api' . _LOG_ERREUR);
}
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 envoie un mail si possible et on echoue en lançant une exception
* @param $sujet
* @param $corps
* @throws Exception
*/
function debardeur_fail($sujet, $corps){
$corps = rtrim($corps) . "\n\n";
//debardeur_envoyer_mail($sujet, $corps);
echo "\n\n$sujet\n$corps\n";
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');
}
function spip_log($message, $logfile='spip') {
}
Loading…
Cancel
Save