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');
42 $this->_addHook('weekly');
46 function getDefaultServer() {
47 return forge_get_config('default_server', 'scmgit') ;
50 function printShortStats ($params) {
51 $project = $this->checkParams($params);
56 if ($project->usesPlugin($this->name)) {
57 $result = db_query_params('SELECT sum(commits) AS commits, sum(adds) AS adds FROM stats_cvs_group WHERE group_id=$1',
58 array ($project->getID())) ;
59 $commit_num = db_result($result,0,'commits');
60 $add_num = db_result($result,0,'adds');
67 echo ' (Git: '.sprintf(_('<strong>%1$s</strong> commits, <strong>%2$s</strong> adds'), number_format($commit_num, 0), number_format($add_num, 0)).")";
72 return '<p>' . _('Documentation for Git is available at <a href="http://git-scm.com/">http://git-scm.com/</a>.') . '</p>';
75 function getInstructionsForAnon($project) {
76 $b = '<h2>' . _('Anonymous Git Access') . '</h2>';
78 $b .= _('This project\'s Git repository can be checked out through anonymous access with the following command.');
82 $b .= '<tt>git clone '.util_make_url ('/anonscm/git/'.$project->getUnixName().'/'.$project->getUnixName().'.git').'</tt><br />';
85 $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',
86 array ($project->getID(),
88 $rows = db_numrows($result);
92 $b .= _('Developer\'s repository');
95 $b .= ngettext('One of this project\'s members also has a personal Git repository that can be checked out anonymously.',
96 'Some of this project\'s members also have personal Git repositories that can be checked out anonymously.',
100 for ($i=0; $i<$rows; $i++) {
101 $user_id = db_result($result,$i,'user_id');
102 $user_name = db_result($result,$i,'user_name');
103 $real_name = db_result($result,$i,'realname');
104 $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 />';
112 function getInstructionsForRW($project) {
114 if (session_loggedin()) {
115 $u = user_get_object(user_getid());
116 $d = $u->getUnixName();
119 if (forge_get_config('use_ssh', 'scmgit')) {
121 $b .= _('Developer Git Access via SSH');
124 $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.');
126 $b .= '<p><tt>git clone git+ssh://'.$d.'@' . $this->getBoxForProject($project) . '/'. forge_get_config('repos_path', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
129 if (forge_get_config('use_dav', 'scmgit')) {
130 $protocol = forge_get_config('use_ssl', 'scmgit')? 'https' : 'http';
132 $b .= _('Developer Git Access via HTTP');
135 $b .= _('Only project developers can access the Git tree via this method. Enter your site password when prompted.');
137 $b .= '<p><tt>git clone '.$protocol.'://'.$d.'@' . $this->getBoxForProject($project) . '/'. forge_get_config('scm_root', 'scmgit') .'/'. $project->getUnixName() .'/'. $project->getUnixName() .'.git</tt></p>' ;
140 if ($validSetup == 0) {
141 $b = '<p class="warning">'._('Missing configuration for access in scmgit.ini : use_ssh and use_dav disabled').'</p>';
144 if (forge_get_config('use_ssh', 'scmgit')) {
146 $b .= _('Developer Git Access via SSH');
149 $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.');
151 $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>' ;
153 if (forge_get_config('use_dav', 'scmgit')) {
154 $protocol = forge_get_config('use_ssl', 'scmgit')? 'https' : 'http';
156 $b .= _('Developer Git Access via HTTP');
159 $b .= _('Only project developers can access the Git tree via this method. Enter your site password when prompted.');
161 $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>' ;
165 if (session_loggedin()) {
166 $u =& user_get_object(user_getid()) ;
167 if ($u->getUnixStatus() == 'A') {
168 $result = db_query_params('SELECT * FROM plugin_scmgit_personal_repos p WHERE p.group_id=$1 AND p.user_id=$2',
169 array ($project->getID(),
171 if ($result && db_numrows ($result) > 0) {
173 $b .= _('Access to your personal repository');
176 $b .= _('You have a personal repository for this project, accessible through SSH with the following method. Enter your site password when prompted.');
178 $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>' ;
180 $glist = $u->getGroups();
181 foreach ($glist as $g) {
182 if ($g->getID() == $project->getID()) {
184 $b .= _('Request a personal repository');
187 $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).');
190 $b .= sprintf (_('<a href="%s">Request a personal repository</a>.'),
191 util_make_url ('/plugins/scmgit/index.php?func=request-personal-repo&group_id='.$project->getID()));
201 function getSnapshotPara($project) {
204 $filename = $project->getUnixName().'-scm-latest.tar'.util_get_compressed_file_extension();
205 if (file_exists(forge_get_config('scm_snapshots_path').'/'.$filename)) {
207 $b .= util_make_link("/snapshots.php?group_id=".$project->getID(),
208 _('Download the nightly snapshot')
215 function printBrowserPage($params) {
216 $project = $this->checkParams($params);
221 if ($project->usesPlugin($this->name)) {
222 if ($params['user_id']) {
223 $user = user_get_object($params['user_id']);
224 echo $project->getUnixName().'/users/'.$user->getUnixName();
225 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>' ;
226 } elseif ($this->browserDisplayable($project)) {
227 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>' ;
232 function getBrowserLinkBlock($project) {
234 $b = $HTML->boxMiddle(_('Git Repository Browser'));
236 $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.');
239 $b .= util_make_link ("/scm/browser.php?group_id=".$project->getID(),
240 _('Browse Git Repository')
246 function getStatsBlock ($project) {
250 $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',
251 array ($project->getID()));
253 if (db_numrows($result) > 0) {
254 // $b .= $HTML->boxMiddle(_('Repository Statistics'));
256 $tableHeaders = array(
261 $b .= $HTML->listTableTop($tableHeaders, false, '', 'repo-history');
264 $total = array('adds' => 0, 'commits' => 0);
266 while($data = db_fetch_array($result)) {
267 $b .= '<tr '. $HTML->boxGetAltRowStyle($i) .'>';
268 $b .= '<td class="halfwidth">' ;
269 $b .= util_make_link_u ($data['user_name'], $data['user_id'], $data['realname']) ;
270 $b .= '</td><td class="onequarterwidth align-right">'.$data['adds']. '</td>'.
271 '<td class="onequarterwidth align-right">'.$data['commits'].'</td></tr>';
272 $total['adds'] += $data['adds'];
273 $total['commits'] += $data['commits'];
276 $b .= '<tr '. $HTML->boxGetAltRowStyle($i) .'>';
277 $b .= '<td class="halfwidth"><strong>'._('Total').':</strong></td>'.
278 '<td class="onequarterwidth align-right"><strong>'.$total['adds']. '</strong></td>'.
279 '<td class="onequarterwidth align-right"><strong>'.$total['commits'].'</strong></td>';
281 $b .= $HTML->listTableBottom();
287 function createOrUpdateRepo($params) {
288 $project = $this->checkParams($params);
293 if (! $project->usesPlugin($this->name)) {
297 $project_name = $project->getUnixName();
298 $root = forge_get_config('repos_path', 'scmgit') . '/' . $project_name;
299 if (!is_dir($root)) {
300 system("mkdir -p $root");
304 $main_repo = $root . '/' . $project_name . '.git' ;
305 if (!is_file("$main_repo/HEAD") && !is_dir("$main_repo/objects") && !is_dir("$main_repo/refs")) {
306 exec("GIT_DIR=\"$main_repo\" git init --bare --shared=group", $result) ;
307 $output .= join("<br />", $result);
309 exec("GIT_DIR=\"$main_repo\" git update-server-info", $result) ;
310 $output .= join("<br />", $result);
311 if (is_file("$main_repo/hooks/post-update.sample")) {
312 rename("$main_repo/hooks/post-update.sample",
313 "$main_repo/hooks/post-update");
315 if (!is_file("$main_repo/hooks/post-update")) {
316 $f = fopen("$main_repo/hooks/post-update", 'w');
317 fwrite($f, "exec git-update-server-info\n");
320 if (is_file ("$main_repo/hooks/post-update")) {
321 system ("chmod +x $main_repo/hooks/post-update") ;
323 system ("echo \"Git repository for $project_name\" > $main_repo/description") ;
324 system ("find $main_repo -type d | xargs chmod g+s") ;
326 if (forge_get_config('use_ssh','scmgit')) {
327 $unix_group = 'scm_' . $project_name ;
328 system ("chgrp -R $unix_group $root") ;
329 system ("chmod g+s $root") ;
330 if ($project->enableAnonSCM()) {
331 system ("chmod g+wX,o+rX-w $root") ;
332 system ("chmod -R g+rwX,o+rX-w $main_repo") ;
334 system ("chmod g+wX,o-rwx $root") ;
335 system ("chmod -R g+rwX,o-rwx $main_repo") ;
338 $unix_user = forge_get_config('apache_user');
339 $unix_group = forge_get_config('apache_group');
340 system ("chown -R $unix_user:$unix_group $main_repo") ;
341 system ("chmod -R g-rwx,o-rwx $main_repo") ;
344 $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',
345 array ($project->getID(),
347 $rows = db_numrows ($result) ;
348 for ($i=0; $i<$rows; $i++) {
349 system ("mkdir -p $root/users") ;
350 $user_name = db_result($result,$i,'user_name');
351 $repodir = $root . '/users/' . $user_name . '.git' ;
353 if (!is_file ("$repodir/HEAD") && !is_dir("$repodir/objects") && !is_dir("$repodir/refs")) {
354 system ("git clone --bare $main_repo $repodir") ;
355 system ("GIT_DIR=\"$repodir\" git update-server-info") ;
356 if (is_file ("$repodir/hooks/post-update.sample")) {
357 rename ("$repodir/hooks/post-update.sample",
358 "$repodir/hooks/post-update") ;
360 if (!is_file ("$repodir/hooks/post-update")) {
361 $f = fopen ("$repodir/hooks/post-update", 'w') ;
362 fwrite ($f, "exec git-update-server-info\n") ;
365 if (is_file ("$repodir/hooks/post-update")) {
366 system ("chmod +x $repodir/hooks/post-update") ;
368 system("echo \"Git repository for user $user_name in project $project_name\" > $repodir/description");
369 system ("chown -R $user_name:$unix_group $repodir") ;
372 if (is_dir ("$root/users")) {
373 if ($project->enableAnonSCM()) {
374 system ("chmod -R g+rX-w,o+rX-w $root/users") ;
376 system ("chmod -R g+rX-w,o-rwx $root/users") ;
379 $params['output'] = $output;
382 function updateRepositoryList($params) {
383 $groups = $this->getGroups();
385 foreach ($groups as $project) {
386 if ($this->browserDisplayable($project)) {
391 $config_dir = forge_get_config('config_path').'/plugins/scmgit';
392 if (!is_dir($config_dir)) {
393 mkdir($config_dir, 0755, true);
395 $fname = $config_dir . '/gitweb.conf' ;
396 $config_f = fopen($fname.'.new', 'w') ;
397 $rootdir = forge_get_config('repos_path', 'scmgit');
398 fwrite($config_f, "\$projectroot = '$rootdir';\n");
399 fwrite($config_f, "\$projects_list = '$config_dir/gitweb.list';\n");
400 fwrite($config_f, "@git_base_url_list = ('". util_make_url('/anonscm/git') . "');\n");
401 fwrite($config_f, "\$logo = '". util_make_url('/plugins/scmgit/git-logo.png') . "';\n");
402 fwrite($config_f, "\$favicon = '". util_make_url('/plugins/scmgit/git-favicon.png')."';\n");
403 fwrite($config_f, "\$stylesheet = '". util_make_url('/plugins/scmgit/gitweb.css')."';\n");
404 fwrite($config_f, "\$javascript = '". util_make_url('/plugins/scmgit/gitweb.js')."';\n");
405 fwrite($config_f, "\$prevent_xss = 'true';\n");
407 chmod ($fname.'.new', 0644) ;
408 rename ($fname.'.new', $fname) ;
410 $fname = $config_dir . '/gitweb.list' ;
412 $f = fopen ($fname.'.new', 'w');
413 foreach ($list as $project) {
414 $repos = $this->getRepositories($rootdir . "/" . $project->getUnixName());
415 foreach ($repos as $repo) {
416 $reldir = substr($repo, strlen($rootdir) + 1);
417 fwrite($f, $reldir . "\n");
421 chmod($fname.'.new', 0644);
422 rename($fname.'.new', $fname);
425 function getRepositories($path) {
426 if (! is_dir($path)) {
430 $entries = scandir($path);
431 foreach ($entries as $entry) {
432 $fullname = $path . "/" . $entry;
433 if (($entry == ".") or ($entry == ".."))
435 if (is_dir($fullname)) {
436 if (is_link($fullname))
438 $result = $this->getRepositories($fullname);
439 $list = array_merge($list, $result);
440 } elseif ($entry == "HEAD") {
447 function gatherStats ($params) {
448 $project = $this->checkParams ($params) ;
453 if (! $project->usesPlugin ($this->name)) {
457 if ($params['mode'] == 'day') {
458 $year = $params ['year'] ;
459 $month = $params ['month'] ;
460 $day = $params ['day'] ;
461 $month_string = sprintf( "%04d%02d", $year, $month );
462 $start_time = gmmktime( 0, 0, 0, $month, $day, $year);
463 $end_time = $start_time + 86400;
465 $usr_adds = array () ;
466 $usr_updates = array () ;
467 $usr_deletes = array () ;
472 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
473 if (!is_dir ($repo) || !is_dir ("$repo/refs")) {
474 // echo "No repository\n" ;
478 $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' ) ;
482 // cleaning stats_cvs_* table for the current day
483 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE month=$1 AND day=$2 AND group_id=$3',
484 array ($month_string,
486 $project->getID())) ;
488 echo "Error while cleaning stats_cvs_group\n" ;
494 while (!feof($pipe) && $data = fgets ($pipe)) {
496 if (strlen($line) > 0) {
497 $result = preg_match("/^(?P<name>.+) <(?P<mail>.+)>/", $line, $matches);
500 $last_user = $matches['name'];
501 $user2email[$last_user] = strtolower($matches['mail']);
502 if (!isset($usr_adds[$last_user])) {
503 $usr_adds[$last_user] = 0;
504 $usr_updates[$last_user] = 0;
505 $usr_deletes[$last_user] = 0;
508 // Short-commit stats line
509 preg_match("/^(?P<mode>[AM])\s+(?P<file>.+)$/", $line, $matches);
510 if ($last_user == "") continue;
511 if ($matches['mode'] == 'A') {
512 $usr_adds[$last_user]++;
514 } elseif ($matches['mode'] == 'M') {
515 $usr_updates[$last_user]++;
517 } elseif ($matches['mode'] == 'D') {
518 $usr_deletes[$last_user]++;
524 // inserting group results in stats_cvs_groups
525 if ($updates > 0 || $adds > 0) {
526 if (!db_query_params ('INSERT INTO stats_cvs_group (month,day,group_id,checkouts,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
527 array ($month_string,
533 echo "Error while inserting into stats_cvs_group\n" ;
539 // building the user list
540 $user_list = array_unique( array_merge( array_keys( $usr_adds ), array_keys( $usr_updates ) ) );
542 foreach ( $user_list as $user ) {
543 // Trying to get user id from user name or email
544 $u = &user_get_object_by_name ($user) ;
546 $user_id = $u->getID();
548 $res=db_query_params('SELECT user_id FROM users WHERE lower(realname)=$1 OR email=$2',
549 array (strtolower($user), $user2email[$user]));
550 if ($res && db_numrows($res) > 0) {
551 $user_id = db_result($res,0,'user_id');
557 $uu = $usr_updates[$user] ? $usr_updates[$user] : 0 ;
558 $ua = $usr_adds[$user] ? $usr_adds[$user] : 0 ;
559 if ($uu > 0 || $ua > 0) {
560 if (!db_query_params ('INSERT INTO stats_cvs_user (month,day,group_id,user_id,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
561 array ($month_string,
567 echo "Error while inserting into stats_cvs_user\n" ;
577 function generateSnapshots ($params) {
579 $project = $this->checkParams ($params) ;
584 $group_name = $project->getUnixName() ;
586 $snapshot = forge_get_config('scm_snapshots_path').'/'.$group_name.'-scm-latest.tar'.util_get_compressed_file_extension();
587 $tarball = forge_get_config('scm_tarballs_path').'/'.$group_name.'-scmroot.tar'.util_get_compressed_file_extension();
589 if (! $project->usesPlugin ($this->name)) {
593 if (! $project->enableAnonSCM()) {
594 if (is_file($snapshot)) {
597 if (is_file($tarball)) {
603 // TODO: ideally we generate one snapshot per git repository
604 $toprepo = forge_get_config('repos_path', 'scmgit') ;
605 $repo = $toprepo . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git' ;
607 if (!is_dir ($repo)) {
608 if (is_file($snapshot)) {
611 if (is_file($tarball)) {
617 // Skip empty repo (no HEAD present in repository)
618 $ref = trim(`GIT_DIR=$repo git symbolic-ref HEAD`);
619 if (!file_exists($repo.'/'.$ref)) {
623 $tmp = trim (`mktemp -d`) ;
627 $today = date ('Y-m-d') ;
628 system ("GIT_DIR=\"$repo\" git archive --format=tar --prefix=$group_name-scm-$today/ HEAD |".forge_get_config('compression_method')." > $tmp/snapshot");
629 chmod ("$tmp/snapshot", 0644) ;
630 copy ("$tmp/snapshot", $snapshot) ;
631 unlink ("$tmp/snapshot") ;
633 system ("tar cCf $toprepo - ".$project->getUnixName() ."|".forge_get_config('compression_method')."> $tmp/tarball") ;
634 chmod ("$tmp/tarball", 0644) ;
635 copy ("$tmp/tarball", $tarball) ;
636 unlink ("$tmp/tarball") ;
637 system ("rm -rf $tmp") ;
641 * widgets - 'widgets' hook handler
642 * @param array $params
645 function widgets($params) {
646 require_once 'common/widget/WidgetLayoutManager.class.php';
647 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_GROUP) {
648 $params['fusionforge_widgets'][] = 'plugin_scmgit_project_latestcommits';
650 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_USER) {
651 $params['fusionforge_widgets'][] = 'plugin_scmgit_user_myrepositories';
657 * Process the 'widget_instance' hook to create instances of the widgets
658 * @param array $params
660 function myPageBox($params) {
662 $user = UserManager::instance()->getCurrentUser();
663 require_once 'common/widget/WidgetLayoutManager.class.php';
664 if ($params['widget'] == 'plugin_scmgit_user_myrepositories') {
665 require_once $gfplugins.$this->name.'/common/scmgit_Widget_MyRepositories.class.php';
666 $params['instance'] = new scmgit_Widget_MyRepositories(WidgetLayoutManager::OWNER_TYPE_USER, $user->getId());
670 function weekly(&$params) {
671 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1 AND use_scm=1 ORDER BY group_id DESC',
674 $params['output'] .= 'ScmGit Plugin: Unable to get list of projects using SCM: '.db_error();
678 $params['output'] .= 'ScmGit Plugin: Running "git gc --quiet" on '.db_numrows($res).' repositories.'."\n";
679 while ($row = db_fetch_array($res)) {
680 $project = group_get_object($row['group_id']);
681 if (!$project || !is_object($project)) {
683 } elseif ($project->isError()) {
686 if (!$project->usesPlugin($this->name)) {
690 $project_name = $project->getUnixName();
691 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project_name . '/' . $project_name .'.git';
694 $params['output'] .= $project_name.': '.`git gc --quiet 2>&1`;
699 function activity($params) {
700 $group_id = $params['group'];
701 $project = group_get_object($group_id);
702 if (! $project->usesPlugin($this->name)) {
705 if (in_array('scmgit', $params['show'])) {
706 $start_time = $params['begin'];
707 $end_time = $params['end'];
708 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
709 $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' );
710 while (!feof($pipe) && $data = fgets($pipe)) {
712 $splitedLine = explode('||', $line);
713 if (sizeof($splitedLine) == 4) {
715 $result['section'] = 'scm';
716 $result['group_id'] = $group_id;
717 $result['ref_id'] = 'browser.php?group_id='.$group_id;
718 $result['description'] = $splitedLine[2].' (commit '.$splitedLine[3].')';
719 $result['realname'] = '';
720 $splitedDate = explode(' ', $splitedLine[0]);
721 $result['activity_date'] = $splitedDate[0];
722 $result['subref_id'] = '';
723 $params['results'][] = $result;
727 $params['ids'][] = $this->name;
728 $params['texts'][] = _('Git Commits');
735 // c-file-style: "bsd"