source: spip-zone/_outils_/smart_paquets/inc_empaqueteur.php @ 45336

Last change on this file since 45336 was 45336, checked in by eric@…, 9 years ago

Changer le nom de l'index des logos pour éviter de perdre l'affichage des zips par défaut

File size: 14.4 KB
Line 
1<?php
2
3// -------------------------------------- APPEL PRINCIPAL ------------------------------------------
4
5// Fonction principale appelee par le script empaqueteur.php
6// Elle lance successivement:
7// 1. la creation des zips et de la base des logos
8// 2. le nettoyage des paquets obsoletes
9// 3. la creation du fichier xml des paquets
10// 4. la creation du fichier des traductions de Salvatore
11// 5. la creation d'un index des logos
12//
13// $url                 : url du repository des sources (ex: svn://zone.spip.org/spip-zone)
14// $dir_repo    : repertoire racine des sources extraits du repository (ex: spip-zone)
15// $dir_paq             : repertoire de depot des paquets crees (ex: paquets)
16// $src                 : nom du fichier listant les archives a creer (ex: archivelist.txt)
17// $dest                : nom sans extension du fichier xml recapitulant toutes les archives (ex: archives)
18// $xml                 : nom du fichier xml contenant les infos des plugins (ex: plugin.xml)
19// $nom_vcs             : gestionnaire de versions motorisant le repository concerne (ex: svn)
20// $mail_to             : destinataire des mails d'information
21// $mail_from   : emetteur des mails d'information
22//
23// return               : aucun
24function empaqueteur($url, $dir_repo, $dir_paq, $src, $dest, $xml, $nom_vcs, $mail_to, $mail_from)
25{
26        global $erreurs;
27        require('inc_outils.php');
28
29        // Determination du producteur a utiliser
30        // - plugin pour l'actuelle DTD
31        // - paquet pour la future DTD
32        $producteur =  'empaqueteur_' . basename($xml, '.xml');
33        require($producteur . '.php');
34
35        $erreurs = array();
36        $url = trim($url);
37        $dir_repo = rtrim($dir_repo ? $dir_repo : basename($url),'/') .'/';
38        $dir_paq = rtrim($dir_paq ? $dir_paq : '.','/') .'/';
39       
40        // 1. creation des zips et de la base des logos
41        list($depot, $zips) = empaqueteur_archives($url, $dir_repo, $dir_paq, $src, $nom_vcs, $xml);
42       
43        // 2. nettoyage des paquets obsoletes
44// -> a prevoir : nettoyage des logos obsoletes aussi
45        if (!$erreurs) {
46                // ne pas nettoyer le fichier archives.xml !
47                $old = array_keys($zips);
48// -> a prevoir : virer la possibilite que $dest soit un tableau
49                foreach(is_array($dest) ? $dest : array($dest) as $nom_dest)
50                        $old[] = $nom_dest . '.xml';
51                nettoyer_vieux_paquets($old, $dir_paq . $dir_repo, $dir_tmp);
52        }
53        elseif ($mail_to) 
54                envoyer_mail($erreurs, $mail_to, $mail_from);
55
56        // Obtention des contenus du fichier xml des paquets et de celui des traductions Salvatore
57        list($archives, $salvatore) = $producteur($depot, $zips);
58       
59        // 3. la creation du fichier xml des paquets
60        if ($archives)
61                empaqueteur_xml_archives($dest . '.xml', $archives, $dir_paq, $dir_repo);
62        else
63                echo_trace("Aucun Zip produit");
64
65        // 4. la creation du fichier des traductions de Salvatore
66        if ($salvatore)
67                empaqueteur_salvatore('traductions.txt', $salvatore, $dir_paq, $dir_repo);
68        else
69                echo_trace("Aucune traduction avec Salvatore");
70
71        // 5. la creation d'un index des logos
72        empaqueteur_index_logos('logos.php', $dir_paq, $dir_repo);
73}
74
75
76// ---------------------------------- CREATION DES ARCHIVES ----------------------------------------
77
78// Fonction de creation des zips et de la base des logos
79// Elle lance successivement:
80// 1. Creation des repertoires de travail et import initial (uniquement la premiere fois)
81// 2. Check-out ou update des sources a archiver
82// 3. Lecture de la liste des archives a creer
83// 4. Creation de la liste des archives requises
84//
85// $url                 : url du repository des sources (ex: svn://zone.spip.org/spip-zone)
86// $dir_repo    : repertoire racine des sources extraits du repository (ex: spip-zone)
87// $dir_paq             : repertoire de depot des paquets crees (ex: paquets)
88// $src                 : nom du fichier listant les archives a creer (ex: archivelist.txt)
89// $nom_vcs             : gestionnaire de versions motorisant le repository concerne (ex: svn)
90// $xml                 : nom du fichier xml contenant les infos des plugins (ex: plugin.xml)
91//
92// return               : tableau des infos du depot et des zips crees
93//                                      0 : tableau associatif (info -> valeur) de chaque info collectee sur le depot
94//                                      1 : tableau associatif (nom de l'archive -> liste des infos) des zips crees
95function empaqueteur_archives($url, $dir_repo, $dir_paq, $src, $nom_vcs, $xml)
96{
97        // Definition des deux sous-repertoires temporaires et definitifs des paquets
98        $dir_tmp = $dir_paq.'tmp/';
99        $dir_paq .= $dir_repo;
100
101        // Test pour savoir si le gestionnaire de version est bien installe sur le serveur
102        if (!function_exists($vcs = 'vcs_exec_' . $nom_vcs)) {
103                echo_trace("VCS non disponible: '$nom_vcs'");
104                $vcs = 'explode'; // i.e. ne fait rien de ses arguments.
105        }
106
107        // 1. Creation des repertoires de travail et import initial
108        if (!file_exists($dir_repo)){
109                preparer_chemin(dirname(rtrim($dir_repo,'/')));
110                if ($url) $vcs("checkout", "$url $dir_repo");
111        }
112        if (!file_exists($dir_paq))
113                preparer_chemin($dir_paq);
114        if (!file_exists($dir_tmp))
115                preparer_chemin($dir_tmp);
116
117        // 2. Check-out ou update des sources a archiver
118        // Si le repo est en file:// on fait un svnsync dessus,
119        // le up est fait par un hook post-commit sur ce qui a change uniquement
120        // sauf une fois par jour
121        if (preg_match(',^file://,',$url)) {
122                $vcs("sync", $url);
123                if (_FORCE_UPDATE)
124                        $vcs("up",rtrim($dir_repo,'/'));
125        }
126        elseif ($url) {
127                $vcs("up", rtrim($dir_repo,'/'));
128        }
129
130        // 3. Lecture de la liste des archives a creer
131        list($depot, $paquets) = lister_paquets($dir_repo . $src);
132
133        // 4. Creation de la liste des archives requises
134        $zips = array();
135        foreach($paquets as $paquet){
136                if ($paquet['revision']=='HEAD' AND
137                    $r = creer_paquet($paquet, $dir_repo, $dir_paq, $dir_tmp, $vcs, $xml)) {
138                        $zips[$paquet['nom'] .".zip"] = $r;
139                        if (intval(_SLEEP_BETWEEN)) usleep(_SLEEP_BETWEEN);
140                }
141        }
142        echo_trace(count($zips) . " trouves");
143
144        return array($depot, $zips);
145}
146
147
148// Lister les paquets demandes dans le fichier des archives
149// et compiler les informations sur le depot
150//
151// $src                 : nom du fichier listant les archives a creer
152//
153// return               : tableau des infos du depot et des archives a creer
154//                                      0 : tableau associatif (info -> valeur) de chaque info collectee sur le depot
155//                                      1 : tableau associatif des archives a creer (source, nom, nom_dossier et revision)
156function lister_paquets($src){
157
158        echo_trace("chargement de $src");
159        if (!$archivefile=file($src)){
160                echo_trace("Erreur : Impossible de lire $src");
161                return array();
162        }
163
164        $depot = array();
165        $paquets = array();
166        foreach($archivefile as $ligne=>$lignepaquet){
167                $lignepaquet=rtrim($lignepaquet);//on vire le retour ligne de la fin
168                if (strlen($lignepaquet)) {
169                        if (substr($lignepaquet,0,1)!="#") {
170                                // C'est une ligne de definition d'un paquet :
171                                // - on separe les parametres
172                                // - et on fixe ceux manquants
173                                $a = explode(";",$lignepaquet);
174                                $b = preg_split("/:/",$a[0]);
175                                $source = $b[0];
176                                $svn_version = empty($b[1]) ?'HEAD' : $b[1];           
177                                $nom_paquet = empty($a[1]) ? basename($source) : $a[1];
178                                $nom_dossier = empty($a[2]) ? $nom_paquet : $a[2];
179                                // Ajout au tableau des paquets a construire
180                                $paquets[] = array('source'=>rtrim($source,'/'),
181                                                   'nom'=>$nom_paquet,
182                                                   'nom_dossier'=>$nom_dossier,
183                                                   'revision'=>$svn_version);
184                        }
185                        else if (preg_match('#@([^=\s]+)\s*=(.+)$#', substr($lignepaquet, 1), $matches)){
186                                // C'est une ligne d'information sur le depot
187                                // - on stocke le parametre trouve
188                                $depot[trim($matches[1])] = trim($matches[2]);
189                        }
190                }
191        }
192
193        echo_trace(count($depot)." informations de depot definies");
194        echo_trace(count($paquets)." paquets definis");
195        return array($depot, $paquets);
196}
197       
198
199// Fonction de creation d'un paquet soit :
200// - de l'archive des sources (zip actuellement)
201// - et de son logo eventuel
202//
203// $paquet              : tableau des infos sur l'archive a creer
204// $dir_repo    : repertoire racine des sources extraits du repository
205// $dir_paq             : repertoire de depot des paquets crees
206// $dir_tmp             : repertoire temporaire de depot des archives crees
207// $vcs                 : fonction d'interface du vcs utilise (ex: vcs_exec_svn)
208// $xml                 : nom du fichier xml contenant les infos des plugins (ex: plugin.xml)
209//
210// return               : tableau des infos sur le paquet cree
211//                                      0 : taille du paquet
212//                                      1 : date du paquet
213//                                      2 : arborescence des sources du paquet (relatif a l'url des sources)
214//                                      3 : date du dernier commit
215//                                      4 : contenu du fichier xml du plugin
216function creer_paquet($paquet, $dir_repo, $dir_paq, $dir_tmp, $vcs, $xml)
217{
218        // Verifier le repertoire source du paquet a creer
219        $dsource = $dir_repo. $paquet['source'];
220        if (!file_exists($dsource)){
221                echo_trace("Erreur : $dsource inexistant");
222                return false;
223        }
224       
225        // Ajouter le fichier svn.revision dans les fichiers de l'archive pour les besoins de SPIP
226        $rev = $dsource . "/svn.revision";
227        $vcs("info", "$dsource > $rev");
228        $info = renseigner_revision_paquet($rev);
229        $zip = $paquet['nom'] .".zip";
230        $zippath = $dir_paq.$zip;
231        if (!archiver($dsource, $zip, $zippath, $paquet['nom_dossier'], $info, $dir_tmp))
232                return false;
233        // -- copier le svn.revision de stable/spip.zip qui permet de connaitre la derniere version stable
234        if ($zip=="stable/spip.zip") {
235                // necessaire de remettre le fichier a la date actuelle
236                // car il a la date du dernier commit sur ce paquet
237                # touch($dsource."/svn.revision");
238                copie_update($rev, $dir_paq.dirname($zip)."/svn.revision");
239        }
240        // -- supprimer le fichier info revision cree ci-dessus
241        @unlink($rev);
242
243        $f = $dsource . '/' . $xml ;
244        if (file_exists($f)) {
245                // Recuperer le xml qui decrit le plugin
246            $re = ",<"."\?xml[^>]*\?".">,Uims";
247                $desc = trim(preg_replace($re,'',file_get_contents($f)));
248
249                // Creer le logo du paquet
250                $f = 'empaqueteur_' . basename($xml, '.xml') . '_logo';
251                $f = !function_exists($f) ? "" : $f($desc, $dsource);
252                if ($f AND file_exists($f) AND preg_match('/[.][^.]*$/', $f, $r)) {
253                        $d = $dir_paq . $paquet['nom'] . $r[0];
254                        copy($f, $d);
255                }
256        }
257        else {
258                // Paquet sans xml correspondant a une contribution quelconque
259                echo_trace("(info) Paquet $zip sans $xml");
260                $desc = '';
261        } 
262       
263        return array(
264                filesize($zippath),
265                filemtime($zippath),
266                $paquet['source'],
267                $info[1],
268                $desc);
269}
270
271
272// Fonction de creation d'une archive des sources contenu dans une arborescence donnee.
273// Aujourd'hui l'archive est toujours un zip
274//
275// $source              : emplacement des sources a archiver
276// $zip                 : nom de l'archive a creer
277// $zippath             : chemin complet de l'archive a creer
278// $nom_dossier : arborescence dans le zip qui sera cree lors du dezippage
279// $rev                 : tableau des informations sur le dernier commit (revision, date)
280// $dir_tmp             : repertoire temporaire de depot des archives creees
281//
282// return               : true/false
283function archiver($source, $zip, $zippath, $nom_dossier, $rev, $dir_tmp){
284        $zipfile = basename($zip);
285        list($revision, $date_commit) = $rev;
286        $date_paquet = file_exists($zippath) ? filemtime($zippath) : 0;
287        // tester si le paquet est a jour
288        if (strtotime($date_commit) < $date_paquet AND !_FORCE_UPDATE) {
289                echo_trace("$zip OK : du ".date('Y-m-d H:i:s',$date_paquet)." / dernier commit du $date_commit");
290                return true;
291        }
292        else {
293                $tmp = $dir_tmp.$nom_dossier;
294                preparer_chemin($tmp);
295                if (!rename($source,$tmp)) {
296                        echo_trace("Erreur : $source --> $tmp");
297                        return false;
298                } else {
299                        $d = getcwd();
300                        chdir($dir_tmp);
301                        $base_dir = reset(explode('/',$nom_dossier));
302                        // zipper en prenant la date du fichier le plus recent
303                        // comme date du paquet
304                        exec_trace("zip -roq $zipfile $base_dir -x \*/.svn\*");
305                        chdir($d);
306
307                        $date_paquet = filemtime($dir_tmp.$zipfile);
308                        // cas ou le dernier commit consiste en la suppression de fichiers
309                        // du coup le zip est plus ancien que le dernier commit
310                        // on corrige manuellement
311                        if ($date_paquet<strtotime($date_commit)) {
312                                touch($dir_tmp.$zipfile,strtotime($date_commit)+1);
313                        }
314                        rename($tmp,$source);
315                }
316                supprimer_chemin($dir_tmp,$nom_dossier);
317                copie_update($dir_tmp.$zipfile,$zippath);
318                return true;
319        }
320}
321
322
323// --------------------------- CREATION DES FICHIERS RESULTAT --------------------------------------
324
325// Fonction creant le fichier xml recapitulant toutes les archives creees
326//
327// Ne pas le reecrire si rien de neuf, c'est + efficace et ca permet
328// au detecteur de nouvelle version d'utiliser If-Modified-Since.
329//
330// Attention, file_put_contents fait ce qu'il veut de certaines lignes vides
331// http://fr2.php.net/manual/fr/function.file-put-contents.php
332//
333// $dest                : nom sans extension du fichier xml recapitulant toutes les archives
334// $archives    : contenu du nouveau fichier xml resultant des archives creees
335// $dir_paq             : repertoire de depot des paquets crees
336// $dir_repo    : repertoire racine des sources extraits du repository
337//
338// return               : aucun
339function empaqueteur_xml_archives($nom_fichier, $archives, $dir_paq, $dir_repo)
340{
341        $taille = strlen($archives);
342        $f = $dir_paq . $dir_repo . $nom_fichier;
343        $old = (file_exists($f)) ? trim(file_get_contents($f)) : '';
344        if ($old != $archives) {
345                echo_trace("Nouveau $f de taille $taille");
346                file_put_contents($f, $archives);
347                return;
348        }
349        echo_trace("$f intact (taille: $taille)");
350}
351
352
353// Fonction creant le fichier des traductions de Salvatore
354//
355// Ne pas le reecrire si rien de neuf, c'est + efficace et ca permet
356// au detecteur de nouvelle version d'utiliser If-Modified-Since.
357//
358// Attention, file_put_contents fait ce qu'il veut de certaines lignes vides
359// http://fr2.php.net/manual/fr/function.file-put-contents.php
360//
361// $salvatore   : contenu du nouveau fichier des traductions Salvatore
362// $dir_paq             : repertoire de depot des paquets crees
363// $dir_repo    : repertoire racine des sources extraits du repository
364//
365// return               : aucun
366function empaqueteur_salvatore($nom_fichier, $salvatore, $dir_paq, $dir_repo)
367{
368        $taille = strlen($salvatore);
369        $fichier = $dir_paq . $dir_repo . $nom_fichier;
370        $old = (file_exists($fichier)) ? trim(file_get_contents($fichier)) : '';
371        if ($old != $salvatore) {
372                echo_trace("Nouveau $fichier de taille $taille");
373                file_put_contents($fichier, $salvatore);
374                return;
375        }
376        echo_trace("$fichier intact (taille: $taille)");
377}
378
379
380// Fonction creant le fichier index des logos permettant d'afficher une page
381// de controle des logos
382//
383// Le fichier est recree systematiquement
384//
385// $dir_paq             : repertoire de depot des paquets crees
386// $dir_repo    : repertoire racine des sources extraits du repository
387//
388// return               : aucun
389function empaqueteur_index_logos($nom_fichier, $dir_paq, $dir_repo)
390{
391        $logos = array_merge(glob($dir_paq . $dir_repo . '*.png'),
392                                                glob($dir_paq . $dir_repo . '*.gif'),
393                                                glob($dir_paq . $dir_repo . '*.jpg'));
394        foreach($logos as $_logo)
395                $contenu .= '<img src="' . basename($_logo) . '" />' . "\n";
396
397        $fichier = $dir_paq . $dir_repo . $nom_fichier;
398        file_put_contents($fichier, $contenu);
399        echo_trace("Nouvel index cree : " . count($logos) . " logos");
400
401        return;
402}
403
404?>
Note: See TracBrowser for help on using the repository browser.