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");
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") ;
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']);
502 // Short-commit stats line
503 preg_match("/^(?P<mode>[AM])\s+(?P<file>.+)$/", $line, $matches);
504 if ($last_user == "") continue;
505 if ($matches['mode'] == 'A') {
506 $usr_adds[$last_user]++;
508 } elseif ($matches['mode'] == 'M') {
509 $usr_updates[$last_user]++;
511 } elseif ($matches['mode'] == 'D') {
512 $usr_deletes[$last_user]++;
518 // inserting group results in stats_cvs_groups
519 if ($updates > 0 || $adds > 0) {
520 if (!db_query_params ('INSERT INTO stats_cvs_group (month,day,group_id,checkouts,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
521 array ($month_string,
527 echo "Error while inserting into stats_cvs_group\n" ;
533 // building the user list
534 $user_list = array_unique( array_merge( array_keys( $usr_adds ), array_keys( $usr_updates ) ) );
536 foreach ( $user_list as $user ) {
537 // Trying to get user id from user name or email
538 $u = &user_get_object_by_name ($user) ;
540 $user_id = $u->getID();
542 $res=db_query_params('SELECT user_id FROM users WHERE lower(realname)=$1 OR email=$2',
543 array (strtolower($user), $user2email[$user]));
544 if ($res && db_numrows($res) > 0) {
545 $user_id = db_result($res,0,'user_id');
551 $uu = $usr_updates[$user] ? $usr_updates[$user] : 0 ;
552 $ua = $usr_adds[$user] ? $usr_adds[$user] : 0 ;
553 if ($uu > 0 || $ua > 0) {
554 if (!db_query_params ('INSERT INTO stats_cvs_user (month,day,group_id,user_id,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
555 array ($month_string,
561 echo "Error while inserting into stats_cvs_user\n" ;
571 function generateSnapshots ($params) {
573 $project = $this->checkParams ($params) ;
578 $group_name = $project->getUnixName() ;
580 $snapshot = forge_get_config('scm_snapshots_path').'/'.$group_name.'-scm-latest.tar'.util_get_compressed_file_extension();
581 $tarball = forge_get_config('scm_tarballs_path').'/'.$group_name.'-scmroot.tar'.util_get_compressed_file_extension();
583 if (! $project->usesPlugin ($this->name)) {
587 if (! $project->enableAnonSCM()) {
588 if (is_file($snapshot)) {
591 if (is_file($tarball)) {
597 // TODO: ideally we generate one snapshot per git repository
598 $toprepo = forge_get_config('repos_path', 'scmgit') ;
599 $repo = $toprepo . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git' ;
601 if (!is_dir ($repo)) {
602 if (is_file($snapshot)) {
605 if (is_file($tarball)) {
611 // Skip empty repo (no HEAD present in repository)
612 $ref = trim(`GIT_DIR=$repo git symbolic-ref HEAD`);
613 if (!file_exists($repo.'/'.$ref)) {
617 $tmp = trim (`mktemp -d`) ;
621 $today = date ('Y-m-d') ;
622 system ("GIT_DIR=\"$repo\" git archive --format=tar --prefix=$group_name-scm-$today/ HEAD |".forge_get_config('compression_method')." > $tmp/snapshot");
623 chmod ("$tmp/snapshot", 0644) ;
624 copy ("$tmp/snapshot", $snapshot) ;
625 unlink ("$tmp/snapshot") ;
627 system ("tar cCf $toprepo - ".$project->getUnixName() ."|".forge_get_config('compression_method')."> $tmp/tarball") ;
628 chmod ("$tmp/tarball", 0644) ;
629 copy ("$tmp/tarball", $tarball) ;
630 unlink ("$tmp/tarball") ;
631 system ("rm -rf $tmp") ;
635 * widgets - 'widgets' hook handler
636 * @param array $params
639 function widgets($params) {
640 require_once 'common/widget/WidgetLayoutManager.class.php';
641 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_GROUP) {
642 $params['fusionforge_widgets'][] = 'plugin_scmgit_project_latestcommits';
644 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_USER) {
645 $params['fusionforge_widgets'][] = 'plugin_scmgit_user_myrepositories';
651 * Process the 'widget_instance' hook to create instances of the widgets
652 * @param array $params
654 function myPageBox($params) {
656 $user = UserManager::instance()->getCurrentUser();
657 require_once 'common/widget/WidgetLayoutManager.class.php';
658 if ($params['widget'] == 'plugin_scmgit_user_myrepositories') {
659 require_once $gfplugins.$this->name.'/common/scmgit_Widget_MyRepositories.class.php';
660 $params['instance'] = new scmgit_Widget_MyRepositories(WidgetLayoutManager::OWNER_TYPE_USER, $user->getId());
664 function weekly(&$params) {
665 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1 AND use_scm=1 ORDER BY group_id DESC',
668 $params['output'] .= 'ScmGit Plugin: Unable to get list of projects using SCM: '.db_error();
672 $params['output'] .= 'ScmGit Plugin: Running "git gc --quiet" on '.db_numrows($res).' repositories.'."\n";
673 while ($row = db_fetch_array($res)) {
674 $project = group_get_object($row['group_id']);
675 if (!$project || !is_object($project)) {
677 } elseif ($project->isError()) {
680 if (!$project->usesPlugin($this->name)) {
684 $project_name = $project->getUnixName();
685 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project_name . '/' . $project_name .'.git';
688 $params['output'] .= $project_name.': '.`git gc --quiet 2>&1`;
693 function activity($params) {
694 $group_id = $params['group'];
695 $project = group_get_object($group_id);
696 if (! $project->usesPlugin($this->name)) {
699 if (in_array('scm', $params['show'])) {
700 $start_time = $params['begin'];
701 $end_time = $params['end'];
702 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
703 $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' );
704 while (!feof($pipe) && $data = fgets($pipe)) {
706 $splitedLine = explode('||', $line);
707 if (sizeof($splitedLine) == 4) {
709 $result['section'] = 'scm';
710 $result['group_id'] = $group_id;
711 $result['ref_id'] = 'browser.php?group_id='.$group_id;
712 $result['description'] = $splitedLine[2].' (commit '.$splitedLine[3].')';
713 $result['realname'] = '';
714 $splitedDate = explode(' ', $splitedLine[0]);
715 $result['activity_date'] = $splitedDate[0];
716 $result['subref_id'] = '';
717 $params['results'][] = $result;
721 $params['ids'][] = 'scm';
722 $params['texts'][] = _('SCM Git Commits');
729 // c-file-style: "bsd"