2 /** FusionForge Bazaar plugin
4 * Copyright 2009, Roland Mas
6 * This file is part of FusionForge.
8 * FusionForge is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2 of the License,
11 * or (at your option) any later version.
13 * FusionForge is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with FusionForge; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 class BzrPlugin extends SCMPlugin {
25 function BzrPlugin () {
28 $this->name = 'scmbzr';
29 $this->text = 'Bazaar';
30 $this->hooks[] = 'scm_generate_snapshots' ;
31 $this->hooks[] = 'scm_browser_page';
32 $this->hooks[] = 'scm_update_repolist' ;
33 $this->hooks[] = 'scm_gather_stats' ;
35 require_once $gfconfig.'plugins/scmbzr/config.php' ;
37 $this->default_bzr_server = $default_bzr_server ;
38 if (isset ($bzr_root)) {
39 $this->bzr_root = $bzr_root;
41 $this->bzr_root = $GLOBALS['sys_chroot'].'/scmrepos/bzr' ;
44 $this->main_branch_names = array () ;
45 $this->main_branch_names[] = 'trunk' ;
46 $this->main_branch_names[] = 'master' ;
47 $this->main_branch_names[] = 'main' ;
48 $this->main_branch_names[] = 'head' ;
49 $this->main_branch_names[] = 'HEAD' ;
54 function getDefaultServer() {
55 return $this->default_bzr_server ;
58 function printShortStats ($params) {
59 $project = $this->checkParams ($params) ;
64 if ($project->usesPlugin($this->name)) {
65 $result = db_query_params('SELECT sum(commits) AS commits, sum(adds) AS adds FROM stats_cvs_group WHERE group_id=$1',
66 array ($project->getID())) ;
67 $commit_num = db_result($result,0,'commits');
68 $add_num = db_result($result,0,'adds');
75 echo ' (Bazaar: '.sprintf(_('<strong>%1$s</strong> commits, <strong>%2$s</strong> adds'), number_format($commit_num, 0), number_format($add_num, 0)).")";
79 function getBlurb () {
80 return _('<p>Documentation for Bazaar (sometimes referred to as "bzr") is available <a href="http://bazaar-vcs.org/Documentation">here</a>.</p>') ;
83 function getInstructionsForAnon ($project) {
84 $b = _('<p><b>Anonymous Bazaar Access</b></p><p>This project\'s Bazaar repository can be checked out through anonymous access with the following command.</p>');
86 $b .= '<tt>bzr checkout '.util_make_url ('/anonscm/bzr/'.$project->getUnixName().'/').'</tt><br />';
91 function getInstructionsForRW ($project) {
93 $b .= _('<p><b>Developer Bazaar Access via SSH</b></p><p>Only project developers can access the Bazaar branches via this method. SSH must be installed on your client machine. Substitute <i>developername</i> with the proper values. Enter your site password when prompted.</p>');
94 $b .= '<p><tt>bzr checkout bzr+ssh://<i>'._('developername').'</i>@' . $project->getSCMBox() . $this->bzr_root .'/'. $project->getUnixName().'/'._('branchname').'</tt></p>' ;
99 function getSnapshotPara ($project) {
103 function getBrowserLinkBlock ($project) {
105 $b = $HTML->boxMiddle(_('Bazaar Repository Browser'));
106 $b .= _('<p>Browsing the Bazaar tree gives you a view into the current status of this project\'s code. You may also view the complete histories of any file in the repository.</p>');
108 $b .= util_make_link ("/scm/browser.php?group_id=".$project->getID(),
109 _('Browse Bazaar Repository')
115 function getStatsBlock ($project) {
119 function printBrowserPage ($params) {
122 $project = $this->checkParams ($params) ;
127 if ($project->usesPlugin ($this->name)) {
128 if ($this->browserDisplayable ($project)) {
129 print '<iframe src="'.util_make_url ("/scm/loggerhead/".$project->getUnixName()).'" frameborder="no" width=100% height=700></iframe>' ;
134 function createOrUpdateRepo ($params) {
135 $project = $this->checkParams ($params) ;
140 if (! $project->usesPlugin ($this->name)) {
144 $repo = $this->bzr_root . '/' . $project->getUnixName() ;
145 $unix_group = 'scm_' . $project->getUnixName() ;
147 $repo_exists = false ;
148 if (is_dir ($repo)) {
149 $pipe = popen ("bzr info $repo 2>/dev/null", "r") ;
150 $line = fgets ($pipe) ;
153 if (preg_match ("/^Shared repository/", $line) != 0) {
154 $repo_exists = true ;
159 system ("mkdir -p $repo") ;
160 system ("bzr init-repo --no-trees $repo >/dev/null") ;
161 system ("find $repo -type d | xargs chmod g+s") ;
164 system ("chgrp -R $unix_group $repo") ;
165 if ($project->enableAnonSCM()) {
166 system ("chmod -R g+wX,o+rX-w $repo") ;
168 system ("chmod -R g+wX,o-rwx $repo") ;
172 function updateRepositoryList ($params) {
173 $groups = $this->getGroups () ;
175 $dir = '/var/lib/gforge/plugins/scmbzr/public-repositories' ;
177 $oldlist = array () ;
178 $dh = opendir ($dir) ;
179 while (($file = readdir($dh)) !== false) {
180 if ($file != '.' && $file != '..') {
187 $newlist = array () ;
188 foreach ($groups as $project) {
189 if ($this->browserDisplayable ($project)) {
190 $newlist[] = $project->getUnixName() ;
195 $dellist = array () ;
196 $createlist = array () ;
198 while (count ($oldlist) > 0 && count ($newlist) > 0) {
202 $createlist[] = array_shift ($newlist) ;
204 $dellist[] = array_shift ($oldlist) ;
206 array_shift ($newlist) ;
207 array_shift ($oldlist) ;
210 $dellist = array_merge ($dellist, $oldlist) ;
211 $createlist = array_merge ($createlist, $newlist) ;
213 foreach ($dellist as $del) {
214 unlink ($dir . '/' . $del) ;
216 foreach ($createlist as $create) {
217 symlink ($this->bzr_root . '/' . $create, $dir . '/' . $create) ;
221 function gatherStats ($params) {
222 $project = $this->checkParams ($params) ;
227 if (! $project->usesPlugin ($this->name)) {
231 if ($params['mode'] == 'day') {
234 $year = $params ['year'] ;
235 $month = $params ['month'] ;
236 $day = $params ['day'] ;
237 $month_string = sprintf( "%04d%02d", $year, $month );
238 $start_time = gmmktime( 0, 0, 0, $month, $day, $year);
239 $end_time = $start_time + 86400;
241 $date = sprintf ("%04d-%02d-%02d", $year, $month, $day);
245 $usr_updates = array () ;
246 $usr_adds = array () ;
248 $toprepo = $this->bzr_root ;
249 $repo = $toprepo . '/' . $project->getUnixName() ;
251 $branch = $this->findMainBranch ($project) ;
258 $pipe = popen ("bzr log file://$repo/$branch --long --verbose 2> /dev/null", 'r' ) ;
260 // cleaning stats_cvs_* table for the current day
261 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE month=$1 AND day=$2 AND group_id=$3',
262 array ($month_string,
264 $project->getID())) ;
266 echo "Error while cleaning stats_cvs_group\n" ;
271 $res = db_query_params ('DELETE FROM stats_cvs_user WHERE month=$1 AND day=$2 AND group_id=$3',
272 array ($month_string,
274 $project->getID())) ;
276 echo "Error while cleaning stats_cvs_user\n" ;
281 // Analyzing history stream
282 $sep = '------------------------------------------------------------' ;
289 while (! feof ($pipe) &&
290 $line = rtrim (fgets ($pipe))) {
292 if ($curdate == $date) {
293 $adds = $adds + $curadds ;
294 $updates = $updates + $curupdates ;
296 if ($curdate != '' && $curdate < $date) {
306 } elseif (preg_match( '/^revno: ([0-9]+)$/', $line, $matches)) {
307 $currev = $matches[1] ;
308 } elseif (preg_match( '/^committer: (.*)$/', $line, $matches)) {
309 $curuser = $matches[1] ;
310 } elseif (preg_match( '/^timestamp: ... (\d\d\d\d-\d\d-\d\d)/', $line, $matches)) {
311 $curdate = $matches[1] ;
312 } elseif (preg_match( '/^modified:/', $line, $matches)) {
313 $state = 'modified' ;
314 } elseif (preg_match( '/^renamed:/', $line, $matches)) {
316 } elseif (preg_match( '/^removed:/', $line, $matches)) {
318 } elseif (preg_match( '/^added/', $line, $matches)) {
331 if ($curdate == $date) {
332 $adds = $adds + $curadds ;
333 $updates = $updates + $curupdates ;
336 // inserting group results in stats_cvs_groups
337 if ($updates > 0 || $adds > 0) {
338 if (!db_query_params ('INSERT INTO stats_cvs_group (month,day,group_id,checkouts,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
339 array ($month_string,
345 echo "Error while inserting into stats_cvs_group\n" ;
351 // building the user list
352 $user_list = array_unique( array_merge( array_keys( $usr_adds ), array_keys( $usr_updates ) ) );
354 foreach ( $user_list as $user ) {
355 // trying to get user id from user name
356 $u = &user_get_object_by_name ($user) ;
358 $user_id = $u->getID();
363 $uu = $usr_updates[$user] ? $usr_updates[$user] : 0 ;
364 $ua = $usr_adds[$user] ? $usr_adds[$user] : 0 ;
365 if ($uu > 0 || $ua > 0) {
366 if (!db_query_params ('INSERT INTO stats_cvs_user (month,day,group_id,user_id,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
367 array ($month_string,
373 echo "Error while inserting into stats_cvs_user\n" ;
383 function findMainBranch ($project) {
384 $toprepo = $this->bzr_root ;
385 $repo = $toprepo . '/' . $project->getUnixName() ;
389 foreach ($this->main_branch_names as $bname) {
390 system ("bzr ls file://$repo/$bname > /dev/null 2>&1", $code) ;
399 function generateSnapshots ($params) {
400 global $sys_scm_snapshots_path ;
401 global $sys_scm_tarballs_path ;
403 $project = $this->checkParams ($params) ;
408 $group_name = $project->getUnixName() ;
410 $snapshot = $sys_scm_snapshots_path.'/'.$group_name.'-scm-latest.tar.gz';
411 $tarball = $sys_scm_tarballs_path.'/'.$group_name.'-scmroot.tar.gz';
413 if (! $project->usesPlugin ($this->name)) {
417 if (! $project->enableAnonSCM()) {
423 $toprepo = $this->bzr_root ;
424 $repo = $toprepo . '/' . $project->getUnixName() ;
426 if (!is_dir ($repo) || !is_file ("$repo/format")) {
432 $tmp = trim (`mktemp -d`) ;
436 $today = date ('Y-m-d') ;
437 $branch = $this->findMainBranch ($project) ;
439 system ("bzr export --root=$group_name-scm-$today $tmp/snapshot.tar.gz $repo/$bname") ;
440 chmod ("$tmp/snapshot.tar.gz", 0644) ;
441 copy ("$tmp/snapshot.tar.gz", $snapshot) ;
442 unlink ("$tmp/snapshot.tar.gz") ;
443 system ("rm -rf $tmp/$dir") ;
448 system ("tar czCf $toprepo $tmp/tarball.tar.gz " . $project->getUnixName()) ;
449 chmod ("$tmp/tarball.tar.gz", 0644) ;
450 copy ("$tmp/tarball.tar.gz", $tarball) ;
451 unlink ("$tmp/tarball.tar.gz") ;
452 system ("rm -rf $tmp") ;
458 // c-file-style: "bsd"