3 * FusionForge Git plugin
5 * Copyright 2009, Roland Mas
6 * Copyright 2009, Mehdi Dogguy <mehdi@debian.org>
7 * Copyright 2012, Franck Villaume - TrivialDev
8 * http://fusionforge.org
10 * This file is part of FusionForge.
12 * FusionForge is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published
14 * by the Free Software Foundation; either version 2 of the License,
15 * or (at your option) any later version.
17 * FusionForge is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 forge_define_config_item('default_server', 'scmgit', forge_get_config ('web_host')) ;
28 forge_define_config_item('repos_path', 'scmgit', forge_get_config('chroot').'/scmrepos/git') ;
30 class GitPlugin extends SCMPlugin {
31 function GitPlugin() {
33 $this->name = 'scmgit';
35 $this->_addHook('scm_browser_page');
36 $this->_addHook('scm_update_repolist');
37 $this->_addHook('scm_generate_snapshots');
38 $this->_addHook('scm_gather_stats');
39 $this->_addHook('widget_instance', 'myPageBox', false);
40 $this->_addHook('widgets', 'widgets', false);
41 $this->_addHook('activity');
45 function getDefaultServer() {
46 return forge_get_config('default_server', 'scmgit') ;
49 function printShortStats ($params) {
50 $project = $this->checkParams($params);
55 if ($project->usesPlugin($this->name)) {
56 $result = db_query_params('SELECT sum(commits) AS commits, sum(adds) AS adds FROM stats_cvs_group WHERE group_id=$1',
57 array ($project->getID())) ;
58 $commit_num = db_result($result,0,'commits');
59 $add_num = db_result($result,0,'adds');
66 echo ' (Git: '.sprintf(_('<strong>%1$s</strong> commits, <strong>%2$s</strong> adds'), number_format($commit_num, 0), number_format($add_num, 0)).")";
71 return '<p>' . _('Documentation for Git is available at <a href="http://git-scm.com/">http://git-scm.com/</a>.') . '</p>';
74 function getInstructionsForAnon($project) {
75 $b = '<h2>' . _('Anonymous Git Access') . '</h2>';
77 $b .= _('This project\'s Git repository can be checked out through anonymous access with the following command.');
81 $b .= '<tt>git clone '.util_make_url ('/anonscm/git/'.$project->getUnixName().'/'.$project->getUnixName().'.git').'</tt><br />';
84 $result = db_query_params('SELECT u.user_id, u.user_name, u.realname FROM plugin_scmgit_personal_repos p, users u WHERE p.group_id=$1 AND u.user_id=p.user_id AND u.unix_status=$2',
85 array ($project->getID(),
87 $rows = db_numrows($result);
91 $b .= _('Developer\'s repository');
94 $b .= ngettext('One of this project\'s members also has a personal Git repository that can be checked out anonymously.',
95 'Some of this project\'s members also have personal Git repositories that can be checked out anonymously.',
99 for ($i=0; $i<$rows; $i++) {
100 $user_id = db_result($result,$i,'user_id');
101 $user_name = db_result($result,$i,'user_name');
102 $real_name = db_result($result,$i,'realname');
103 $b .= '<tt>git clone '.util_make_url('/anonscm/git/'.$project->getUnixName().'/users/'.$user_name.'.git').'</tt> ('.util_make_link_u ($user_name, $user_id, $real_name).') ['.util_make_link('/scm/browser.php?group_id='.$project->getID().'&user_id='.$user_id, _('Browse Git Repository')).']<br />';
111 function getInstructionsForRW($project) {
113 if (session_loggedin()) {
114 $u = user_get_object(user_getid());
115 $d = $u->getUnixName();
118 if (forge_get_config('use_ssh', 'scmgit')) {
120 $b .= _('Developer Git Access via SSH');
123 $b .= _('Only project developers can access the Git tree via this method. SSH must be installed on your client machine. Enter your site password when prompted.');
125 $b .= '<p><tt>git clone git+ssh://'.$d.'@' . $this->getBoxForProject($project) . '/'. forge_get_config('repos_path', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
128 if (forge_get_config('use_dav', 'scmgit')) {
129 $protocol = forge_get_config('use_ssl', 'scmgit')? 'https' : 'http';
131 $b .= _('Developer Git Access via HTTP');
134 $b .= _('Only project developers can access the Git tree via this method. Enter your site password when prompted.');
136 $b .= '<p><tt>git clone '.$protocol.'://'.$d.'@' . $this->getBoxForProject($project) . '/'. forge_get_config('scm_root', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
139 if ($validSetup == 0) {
140 $b = '<p class="warning">'._('Missing configuration for access in scmgit.ini : use_ssh and use_dav disabled').'</p>';
143 if (forge_get_config('use_ssh', 'scmgit')) {
145 $b .= _('Developer Git Access via SSH');
148 $b .= _('Only project developers can access the Git tree via this method. SSH must be installed on your client machine. Substitute <i>developername</i> with the proper value. Enter your site password when prompted.');
150 $b .= '<p><tt>git clone git+ssh://<i>'._('developername').'</i>@' . $this->getBoxForProject($project) . '/'. forge_get_config('repos_path', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
152 if (forge_get_config('use_dav', 'scmgit')) {
153 $protocol = forge_get_config('use_ssl', 'scmgit')? 'https' : 'http';
155 $b .= _('Developer Git Access via HTTP');
158 $b .= _('Only project developers can access the Git tree via this method. Enter your site password when prompted.');
160 $b .= '<p><tt>git clone '.$protocol.'://<i>'._('developername').'</i>@' . $this->getBoxForProject($project) . '/'. forge_get_config('scm_root', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
164 if (session_loggedin()) {
165 $u =& user_get_object(user_getid()) ;
166 if ($u->getUnixStatus() == 'A') {
167 $result = db_query_params('SELECT * FROM plugin_scmgit_personal_repos p WHERE p.group_id=$1 AND p.user_id=$2',
168 array ($project->getID(),
170 if ($result && db_numrows ($result) > 0) {
172 $b .= _('Access to your personal repository');
175 $b .= _('You have a personal repository for this project, accessible through SSH with the following method. Enter your site password when prompted.');
177 $b .= '<p><tt>git clone git+ssh://'.$u->getUnixName().'@' . $this->getBoxForProject($project) . '/'. forge_get_config('repos_path', 'scmgit') .'/'. $project->getUnixName() .'/users/'. $u->getUnixName() .'.git</tt></p>' ;
179 $glist = $u->getGroups();
180 foreach ($glist as $g) {
181 if ($g->getID() == $project->getID()) {
183 $b .= _('Request a personal repository');
186 $b .= _('You can clone the project repository into a personal one into which you alone will be able to write. Other members of the project will only have read access. Access for non-members will follow the same rules as for the project\'s main repository. Note that the personal repository may take some time before it is created (less than an hour in most situations).');
189 $b .= sprintf (_('<a href="%s">Request a personal repository</a>.'),
190 util_make_url ('/plugins/scmgit/index.php?func=request-personal-repo&group_id='.$project->getID()));
200 function getSnapshotPara($project) {
203 $filename = $project->getUnixName().'-scm-latest.tar'.util_get_compressed_file_extension();
204 if (file_exists(forge_get_config('scm_snapshots_path').'/'.$filename)) {
206 $b .= util_make_link("/snapshots.php?group_id=".$project->getID(),
207 _('Download the nightly snapshot')
214 function printBrowserPage($params) {
215 $project = $this->checkParams($params);
220 if ($project->usesPlugin($this->name)) {
221 if ($params['user_id']) {
222 $user = user_get_object($params['user_id']);
223 echo $project->getUnixName().'/users/'.$user->getUnixName();
224 print '<iframe src="'.util_make_url("/plugins/scmgit/cgi-bin/gitweb.cgi?p=".$project->getUnixName().'/users/'.$user->getUnixName().'.git').'" frameborder="0" width=100% height=700></iframe>' ;
225 } elseif ($this->browserDisplayable($project)) {
226 print '<iframe src="'.util_make_url("/plugins/scmgit/cgi-bin/gitweb.cgi?p=".$project->getUnixName().'/'.$project->getUnixName().'.git').'" frameborder="0" width=100% height=700></iframe>' ;
231 function getBrowserLinkBlock($project) {
233 $b = $HTML->boxMiddle(_('Git Repository Browser'));
235 $b .= _('Browsing the Git 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.');
238 $b .= util_make_link ("/scm/browser.php?group_id=".$project->getID(),
239 _('Browse Git Repository')
245 function getStatsBlock ($project) {
249 $result = db_query_params('SELECT u.realname, u.user_name, u.user_id, sum(commits) as commits, sum(adds) as adds, sum(adds+commits) as combined FROM stats_cvs_user s, users u WHERE group_id=$1 AND s.user_id=u.user_id AND (commits>0 OR adds >0) GROUP BY u.user_id, realname, user_name, u.user_id ORDER BY combined DESC, realname',
250 array ($project->getID()));
252 if (db_numrows($result) > 0) {
253 // $b .= $HTML->boxMiddle(_('Repository Statistics'));
255 $tableHeaders = array(
260 $b .= $HTML->listTableTop($tableHeaders, false, '', 'repo-history');
263 $total = array('adds' => 0, 'commits' => 0);
265 while($data = db_fetch_array($result)) {
266 $b .= '<tr '. $HTML->boxGetAltRowStyle($i) .'>';
267 $b .= '<td class="halfwidth">' ;
268 $b .= util_make_link_u ($data['user_name'], $data['user_id'], $data['realname']) ;
269 $b .= '</td><td class="onequarterwidth align-right">'.$data['adds']. '</td>'.
270 '<td class="onequarterwidth align-right">'.$data['commits'].'</td></tr>';
271 $total['adds'] += $data['adds'];
272 $total['commits'] += $data['commits'];
275 $b .= '<tr '. $HTML->boxGetAltRowStyle($i) .'>';
276 $b .= '<td class="halfwidth"><strong>'._('Total').':</strong></td>'.
277 '<td class="onequarterwidth align-right"><strong>'.$total['adds']. '</strong></td>'.
278 '<td class="onequarterwidth align-right"><strong>'.$total['commits'].'</strong></td>';
280 $b .= $HTML->listTableBottom();
286 function createOrUpdateRepo($params) {
287 $project = $this->checkParams($params);
292 if (! $project->usesPlugin($this->name)) {
296 $project_name = $project->getUnixName();
297 $root = forge_get_config('repos_path', 'scmgit') . '/' . $project_name;
298 if (!is_dir($root)) {
299 system("mkdir -p $root");
303 $main_repo = $root . '/' . $project_name . '.git' ;
304 if (!is_file("$main_repo/HEAD") && !is_dir("$main_repo/objects") && !is_dir("$main_repo/refs")) {
305 exec("GIT_DIR=\"$main_repo\" git init --bare --shared=group", $result) ;
306 $output .= join("<br />", $result);
308 exec("GIT_DIR=\"$main_repo\" git update-server-info", $result) ;
309 $output .= join("<br />", $result);
310 if (is_file("$main_repo/hooks/post-update.sample")) {
311 rename("$main_repo/hooks/post-update.sample",
312 "$main_repo/hooks/post-update");
314 if (!is_file("$main_repo/hooks/post-update")) {
315 $f = fopen("$main_repo/hooks/post-update", 'w');
316 fwrite($f, "exec git-update-server-info\n");
319 if (is_file ("$main_repo/hooks/post-update")) {
320 system ("chmod +x $main_repo/hooks/post-update") ;
322 system ("echo \"Git repository for $project_name\" > $main_repo/description") ;
323 system ("find $main_repo -type d | xargs chmod g+s") ;
325 if (forge_get_config('use_ssh','scmgit')) {
326 $unix_group = 'scm_' . $project_name ;
327 system ("chgrp -R $unix_group $root") ;
328 system ("chmod g+s $root") ;
329 if ($project->enableAnonSCM()) {
330 system ("chmod g+wX,o+rX-w $root") ;
331 system ("chmod -R g+rwX,o+rX-w $main_repo") ;
333 system ("chmod g+wX,o-rwx $root") ;
334 system ("chmod -R g+rwX,o-rwx $main_repo") ;
337 $unix_user = forge_get_config('apache_user');
338 $unix_group = forge_get_config('apache_group');
339 system ("chown -R $unix_user:$unix_group $main_repo") ;
340 system ("chmod -R g-rwx,o-rwx $main_repo") ;
343 $result = db_query_params ('SELECT u.user_name FROM plugin_scmgit_personal_repos p, users u WHERE p.group_id=$1 AND u.user_id=p.user_id AND u.unix_status=$2',
344 array ($project->getID(),
346 $rows = db_numrows ($result) ;
347 for ($i=0; $i<$rows; $i++) {
348 system ("mkdir -p $root/users") ;
349 $user_name = db_result($result,$i,'user_name');
350 $repodir = $root . '/users/' . $user_name . '.git' ;
352 if (!is_file ("$repodir/HEAD") && !is_dir("$repodir/objects") && !is_dir("$repodir/refs")) {
353 system ("git clone --bare $main_repo $repodir") ;
354 system ("GIT_DIR=\"$repodir\" git update-server-info") ;
355 if (is_file ("$repodir/hooks/post-update.sample")) {
356 rename ("$repodir/hooks/post-update.sample",
357 "$repodir/hooks/post-update") ;
359 if (!is_file ("$repodir/hooks/post-update")) {
360 $f = fopen ("$repodir/hooks/post-update", 'w') ;
361 fwrite ($f, "exec git-update-server-info\n") ;
364 if (is_file ("$repodir/hooks/post-update")) {
365 system ("chmod +x $repodir/hooks/post-update") ;
367 system("echo \"Git repository for user $user_name in project $project_name\" > $repodir/description");
368 system ("chown -R $user_name:$unix_group $repodir") ;
371 if (is_dir ("$root/users")) {
372 if ($project->enableAnonSCM()) {
373 system ("chmod -R g+rX-w,o+rX-w $root/users") ;
375 system ("chmod -R g+rX-w,o-rwx $root/users") ;
378 $params['output'] = $output;
381 function updateRepositoryList($params) {
382 $groups = $this->getGroups();
384 foreach ($groups as $project) {
385 if ($this->browserDisplayable($project)) {
390 $config_dir = forge_get_config('config_path').'/plugins/scmgit';
391 if (!is_dir($config_dir)) {
392 mkdir($config_dir, 0755, true);
394 $fname = $config_dir . '/gitweb.conf' ;
395 $config_f = fopen($fname.'.new', 'w') ;
396 $rootdir = forge_get_config('repos_path', 'scmgit');
397 fwrite($config_f, "\$projectroot = '$rootdir';\n");
398 fwrite($config_f, "\$projects_list = '$config_dir/gitweb.list';\n");
399 fwrite($config_f, "@git_base_url_list = ('". util_make_url('/anonscm/git') . "');\n");
400 fwrite($config_f, "\$logo = '". util_make_url('/plugins/scmgit/git-logo.png') . "';\n");
401 fwrite($config_f, "\$favicon = '". util_make_url('/plugins/scmgit/git-favicon.png')."';\n");
402 fwrite($config_f, "\$stylesheet = '". util_make_url('/plugins/scmgit/gitweb.css')."';\n");
403 fwrite($config_f, "\$javascript = '". util_make_url('/plugins/scmgit/gitweb.js')."';\n");
404 fwrite($config_f, "\$prevent_xss = 'true';\n");
406 chmod ($fname.'.new', 0644) ;
407 rename ($fname.'.new', $fname) ;
409 $fname = $config_dir . '/gitweb.list' ;
411 $f = fopen ($fname.'.new', 'w');
412 foreach ($list as $project) {
413 $repos = $this->getRepositories($rootdir . "/" . $project->getUnixName());
414 foreach ($repos as $repo) {
415 $reldir = substr($repo, strlen($rootdir) + 1);
416 fwrite($f, $reldir . "\n");
420 chmod($fname.'.new', 0644);
421 rename($fname.'.new', $fname);
424 function getRepositories($path) {
425 if (! is_dir($path)) {
429 $entries = scandir($path);
430 foreach ($entries as $entry) {
431 $fullname = $path . "/" . $entry;
432 if (($entry == ".") or ($entry == ".."))
434 if (is_dir($fullname)) {
435 if (is_link($fullname))
437 $result = $this->getRepositories($fullname);
438 $list = array_merge($list, $result);
439 } elseif ($entry == "HEAD") {
446 function gatherStats ($params) {
447 $project = $this->checkParams ($params) ;
452 if (! $project->usesPlugin ($this->name)) {
456 if ($params['mode'] == 'day') {
457 $year = $params ['year'] ;
458 $month = $params ['month'] ;
459 $day = $params ['day'] ;
460 $month_string = sprintf( "%04d%02d", $year, $month );
461 $start_time = gmmktime( 0, 0, 0, $month, $day, $year);
462 $end_time = $start_time + 86400;
464 $usr_adds = array () ;
465 $usr_updates = array () ;
466 $usr_deletes = array () ;
471 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
472 if (!is_dir ($repo) || !is_dir ("$repo/refs")) {
473 // echo "No repository\n" ;
477 $pipe = popen ("GIT_DIR=\"$repo\" git log --since=@$start_time --until=@$end_time --all --pretty='format:%n%an <%ae>' --name-status 2>/dev/null", 'r' ) ;
481 // cleaning stats_cvs_* table for the current day
482 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE month=$1 AND day=$2 AND group_id=$3',
483 array ($month_string,
485 $project->getID())) ;
487 echo "Error while cleaning stats_cvs_group\n" ;
493 while (!feof($pipe) && $data = fgets ($pipe)) {
495 if (strlen($line) > 0) {
496 $result = preg_match("/^(?P<name>.+) <(?P<mail>.+)>/", $line, $matches);
499 $last_user = $matches['name'];
500 $user2email[$last_user] = strtolower($matches['mail']);
501 if (!isset($usr_adds[$last_user])) {
502 $usr_adds[$last_user] = 0;
503 $usr_updates[$last_user] = 0;
504 $usr_deletes[$last_user] = 0;
507 // Short-commit stats line
508 preg_match("/^(?P<mode>[AM])\s+(?P<file>.+)$/", $line, $matches);
509 if ($last_user == "") continue;
510 if ($matches['mode'] == 'A') {
511 $usr_adds[$last_user]++;
513 } elseif ($matches['mode'] == 'M') {
514 $usr_updates[$last_user]++;
516 } elseif ($matches['mode'] == 'D') {
517 $usr_deletes[$last_user]++;
523 // inserting group results in stats_cvs_groups
524 if ($updates > 0 || $adds > 0) {
525 if (!db_query_params ('INSERT INTO stats_cvs_group (month,day,group_id,checkouts,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
526 array ($month_string,
532 echo "Error while inserting into stats_cvs_group\n" ;
538 // building the user list
539 $user_list = array_unique( array_merge( array_keys( $usr_adds ), array_keys( $usr_updates ) ) );
541 foreach ( $user_list as $user ) {
542 // Trying to get user id from user name or email
543 $u = &user_get_object_by_name ($user) ;
545 $user_id = $u->getID();
547 $res=db_query_params('SELECT user_id FROM users WHERE lower(realname)=$1 OR email=$2',
548 array (strtolower($user), $user2email[$user]));
549 if ($res && db_numrows($res) > 0) {
550 $user_id = db_result($res,0,'user_id');
556 $uu = $usr_updates[$user] ? $usr_updates[$user] : 0 ;
557 $ua = $usr_adds[$user] ? $usr_adds[$user] : 0 ;
558 if ($uu > 0 || $ua > 0) {
559 if (!db_query_params ('INSERT INTO stats_cvs_user (month,day,group_id,user_id,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
560 array ($month_string,
566 echo "Error while inserting into stats_cvs_user\n" ;
576 function generateSnapshots ($params) {
578 $project = $this->checkParams ($params) ;
583 $group_name = $project->getUnixName() ;
585 $snapshot = forge_get_config('scm_snapshots_path').'/'.$group_name.'-scm-latest.tar'.util_get_compressed_file_extension();
586 $tarball = forge_get_config('scm_tarballs_path').'/'.$group_name.'-scmroot.tar'.util_get_compressed_file_extension();
588 if (! $project->usesPlugin ($this->name)) {
592 if (! $project->enableAnonSCM()) {
593 if (is_file($snapshot)) {
596 if (is_file($tarball)) {
602 // TODO: ideally we generate one snapshot per git repository
603 $toprepo = forge_get_config('repos_path', 'scmgit') ;
604 $repo = $toprepo . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git' ;
606 if (!is_dir ($repo)) {
607 if (is_file($snapshot)) {
610 if (is_file($tarball)) {
616 // Skip empty repo (no HEAD present in repository)
617 $ref = trim(`GIT_DIR=$repo git symbolic-ref HEAD`);
618 if (!file_exists($repo.'/'.$ref)) {
622 $tmp = trim (`mktemp -d`) ;
626 $today = date ('Y-m-d') ;
627 system ("GIT_DIR=\"$repo\" git archive --format=tar --prefix=$group_name-scm-$today/ HEAD |".forge_get_config('compression_method')." > $tmp/snapshot");
628 chmod ("$tmp/snapshot", 0644) ;
629 copy ("$tmp/snapshot", $snapshot) ;
630 unlink ("$tmp/snapshot") ;
632 system ("tar cCf $toprepo - ".$project->getUnixName() ."|".forge_get_config('compression_method')."> $tmp/tarball") ;
633 chmod ("$tmp/tarball", 0644) ;
634 copy ("$tmp/tarball", $tarball) ;
635 unlink ("$tmp/tarball") ;
636 system ("rm -rf $tmp") ;
640 * widgets - 'widgets' hook handler
641 * @param array $params
644 function widgets($params) {
645 require_once 'common/widget/WidgetLayoutManager.class.php';
646 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_GROUP) {
647 $params['fusionforge_widgets'][] = 'plugin_scmgit_project_latestcommits';
649 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_USER) {
650 $params['fusionforge_widgets'][] = 'plugin_scmgit_user_myrepositories';
656 * Process the 'widget_instance' hook to create instances of the widgets
657 * @param array $params
659 function myPageBox($params) {
661 $user = UserManager::instance()->getCurrentUser();
662 require_once 'common/widget/WidgetLayoutManager.class.php';
663 if ($params['widget'] == 'plugin_scmgit_user_myrepositories') {
664 require_once $gfplugins.$this->name.'/common/scmgit_Widget_MyRepositories.class.php';
665 $params['instance'] = new scmgit_Widget_MyRepositories(WidgetLayoutManager::OWNER_TYPE_USER, $user->getId());
669 function weekly(&$params) {
670 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1 AND use_scm=1 ORDER BY group_id DESC',
673 $params['output'] .= 'ScmGit Plugin: Unable to get list of projects using SCM: '.db_error();
677 $params['output'] .= 'ScmGit Plugin: Running "git gc --quiet" on '.db_numrows($res).' repositories.'."\n";
678 while ($row = db_fetch_array($res)) {
679 $project = group_get_object($row['group_id']);
680 if (!$project || !is_object($project)) {
682 } elseif ($project->isError()) {
685 if (!$project->usesPlugin($this->name)) {
689 $project_name = $project->getUnixName();
690 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project_name . '/' . $project_name .'.git';
693 $params['output'] .= $project_name.': '.`git gc --quiet 2>&1`;
698 function activity($params) {
699 $group_id = $params['group'];
700 $project = group_get_object($group_id);
701 if (! $project->usesPlugin($this->name)) {
704 if (in_array('scm', $params['show'])) {
705 $start_time = $params['begin'];
706 $end_time = $params['end'];
707 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
708 $pipe = popen("GIT_DIR=\"$repo\" git log --date=raw --since=@$start_time --until=@$end_time --all --pretty='format:%ad||%an||%s||%h' --name-status", 'r' );
709 while (!feof($pipe) && $data = fgets($pipe)) {
711 $splitedLine = explode('||', $line);
712 if (sizeof($splitedLine) == 4) {
714 $result['section'] = 'scm';
715 $result['group_id'] = $group_id;
716 $result['ref_id'] = 'browser.php?group_id='.$group_id;
717 $result['description'] = $splitedLine[2].' (commit '.$splitedLine[3].')';
718 $result['realname'] = '';
719 $splitedDate = explode(' ', $splitedLine[0]);
720 $result['activity_date'] = $splitedDate[0];
721 $result['subref_id'] = '';
722 $params['results'][] = $result;
726 $params['ids'][] = 'scm';
727 $params['texts'][] = _('SCM Git Commits');
734 // c-file-style: "bsd"