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 } else if ($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+wX,o+rX-w $main_repo") ;
333 system ("chmod g+wX,o-rwx $root") ;
334 system ("chmod -R g+wX,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, "\$prevent_xss = 'true';\n");
405 chmod ($fname.'.new', 0644) ;
406 rename ($fname.'.new', $fname) ;
408 $fname = $config_dir . '/gitweb.list' ;
410 $f = fopen ($fname.'.new', 'w');
411 foreach ($list as $project) {
412 $repos = $this->getRepositories($rootdir . "/" . $project->getUnixName());
413 foreach ($repos as $repo) {
414 $reldir = substr($repo, strlen($rootdir) + 1);
415 fwrite($f, $reldir . "\n");
419 chmod($fname.'.new', 0644);
420 rename($fname.'.new', $fname);
423 function getRepositories($path) {
424 if (! is_dir($path)) {
428 $entries = scandir($path);
429 foreach ($entries as $entry) {
430 $fullname = $path . "/" . $entry;
431 if (($entry == ".") or ($entry == ".."))
433 if (is_dir($fullname)) {
434 if (is_link($fullname))
436 $result = $this->getRepositories($fullname);
437 $list = array_merge($list, $result);
438 } else if ($entry == "HEAD") {
445 function gatherStats ($params) {
446 $project = $this->checkParams ($params) ;
451 if (! $project->usesPlugin ($this->name)) {
455 if ($params['mode'] == 'day') {
456 $year = $params ['year'] ;
457 $month = $params ['month'] ;
458 $day = $params ['day'] ;
459 $month_string = sprintf( "%04d%02d", $year, $month );
460 $start_time = gmmktime( 0, 0, 0, $month, $day, $year);
461 $end_time = $start_time + 86400;
463 $usr_adds = array () ;
464 $usr_updates = array () ;
465 $usr_deletes = array () ;
470 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
471 if (!is_dir ($repo) || !is_dir ("$repo/refs")) {
472 // echo "No repository\n" ;
476 $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' ) ;
480 // cleaning stats_cvs_* table for the current day
481 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE month=$1 AND day=$2 AND group_id=$3',
482 array ($month_string,
484 $project->getID())) ;
486 echo "Error while cleaning stats_cvs_group\n" ;
492 while (!feof($pipe) && $data = fgets ($pipe)) {
494 if (strlen($line) > 0) {
495 $result = preg_match("/^(?P<name>.+) <(?P<mail>.+)>/", $line, $matches);
498 $last_user = $matches['name'];
499 $user2email[$last_user] = strtolower($matches['mail']);
501 // Short-commit stats line
502 preg_match("/^(?P<mode>[AM])\s+(?P<file>.+)$/", $line, $matches);
503 if ($last_user == "") continue;
504 if ($matches['mode'] == 'A') {
505 $usr_adds[$last_user]++;
507 } elseif ($matches['mode'] == 'M') {
508 $usr_updates[$last_user]++;
510 } elseif ($matches['mode'] == 'D') {
511 $usr_deletes[$last_user]++;
517 // inserting group results in stats_cvs_groups
518 if ($updates > 0 || $adds > 0) {
519 if (!db_query_params ('INSERT INTO stats_cvs_group (month,day,group_id,checkouts,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
520 array ($month_string,
526 echo "Error while inserting into stats_cvs_group\n" ;
532 // building the user list
533 $user_list = array_unique( array_merge( array_keys( $usr_adds ), array_keys( $usr_updates ) ) );
535 foreach ( $user_list as $user ) {
536 // Trying to get user id from user name or email
537 $u = &user_get_object_by_name ($user) ;
539 $user_id = $u->getID();
541 $res=db_query_params('SELECT user_id FROM users WHERE lower(realname)=$1 OR email=$2',
542 array (strtolower($user), $user2email[$user]));
543 if ($res && db_numrows($res) > 0) {
544 $user_id = db_result($res,0,'user_id');
550 $uu = $usr_updates[$user] ? $usr_updates[$user] : 0 ;
551 $ua = $usr_adds[$user] ? $usr_adds[$user] : 0 ;
552 if ($uu > 0 || $ua > 0) {
553 if (!db_query_params ('INSERT INTO stats_cvs_user (month,day,group_id,user_id,commits,adds) VALUES ($1,$2,$3,$4,$5,$6)',
554 array ($month_string,
560 echo "Error while inserting into stats_cvs_user\n" ;
570 function generateSnapshots ($params) {
572 $project = $this->checkParams ($params) ;
577 $group_name = $project->getUnixName() ;
579 $snapshot = forge_get_config('scm_snapshots_path').'/'.$group_name.'-scm-latest.tar'.util_get_compressed_file_extension();
580 $tarball = forge_get_config('scm_tarballs_path').'/'.$group_name.'-scmroot.tar'.util_get_compressed_file_extension();
582 if (! $project->usesPlugin ($this->name)) {
586 if (! $project->enableAnonSCM()) {
587 if (is_file($snapshot)) {
590 if (is_file($tarball)) {
596 // TODO: ideally we generate one snapshot per git repository
597 $toprepo = forge_get_config('repos_path', 'scmgit') ;
598 $repo = $toprepo . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git' ;
600 if (!is_dir ($repo)) {
601 if (is_file($snapshot)) {
604 if (is_file($tarball)) {
610 // Skip empty repo (no HEAD present in repository)
611 $ref = trim(`GIT_DIR=$repo git symbolic-ref HEAD`);
612 if (!file_exists($repo.'/'.$ref)) {
616 $tmp = trim (`mktemp -d`) ;
620 $today = date ('Y-m-d') ;
621 system ("GIT_DIR=\"$repo\" git archive --format=tar --prefix=$group_name-scm-$today/ HEAD |".forge_get_config('compression_method')." > $tmp/snapshot");
622 chmod ("$tmp/snapshot", 0644) ;
623 copy ("$tmp/snapshot", $snapshot) ;
624 unlink ("$tmp/snapshot") ;
626 system ("tar cCf $toprepo - ".$project->getUnixName() ."|".forge_get_config('compression_method')."> $tmp/tarball") ;
627 chmod ("$tmp/tarball", 0644) ;
628 copy ("$tmp/tarball", $tarball) ;
629 unlink ("$tmp/tarball") ;
630 system ("rm -rf $tmp") ;
634 * widgets - 'widgets' hook handler
635 * @param array $params
638 function widgets($params) {
639 require_once('common/widget/WidgetLayoutManager.class.php');
640 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_GROUP) {
641 $params['fusionforge_widgets'][] = 'plugin_scmgit_project_latestcommits';
643 if ($params['owner_type'] == WidgetLayoutManager::OWNER_TYPE_USER) {
644 $params['fusionforge_widgets'][] = 'plugin_scmgit_user_myrepositories';
650 * Process the 'widget_instance' hook to create instances of the widgets
651 * @param array $params
653 function myPageBox($params) {
655 $user = UserManager::instance()->getCurrentUser();
656 require_once('common/widget/WidgetLayoutManager.class.php');
657 if ($params['widget'] == 'plugin_scmgit_user_myrepositories') {
658 require_once $gfplugins.$this->name.'/common/scmgit_Widget_MyRepositories.class.php';
659 $params['instance'] = new scmgit_Widget_MyRepositories(WidgetLayoutManager::OWNER_TYPE_USER, $user->getId());
663 function weekly(&$params) {
664 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1 AND use_scm=1 ORDER BY group_id DESC',
667 $params['output'] .= 'ScmGit Plugin: Unable to get list of projects using SCM: '.db_error();
671 $params['output'] .= 'ScmGit Plugin: Running "git gc --quiet" on '.db_numrows($res).' repositories.'."\n";
672 while ($row = db_fetch_array($res)) {
673 $project = group_get_object($row['group_id']);
674 if (!$project || !is_object($project)) {
676 } elseif ($project->isError()) {
679 if (!$project->usesPlugin($this->name)) {
683 $project_name = $project->getUnixName();
684 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project_name . '/' . $project_name .'.git';
687 $params['output'] .= $project_name.': '.`git gc --quiet 2>&1`;
692 function activity($params) {
693 $group_id = $params['group'];
694 $project = group_get_object($group_id);
695 if (! $project->usesPlugin($this->name)) {
698 if (in_array('scm', $params['show'])) {
699 $start_time = $params['begin'];
700 $end_time = $params['end'];
701 $repo = forge_get_config('repos_path', 'scmgit') . '/' . $project->getUnixName() . '/' . $project->getUnixName() . '.git';
702 $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' );
703 while (!feof($pipe) && $data = fgets($pipe)) {
705 $splitedLine = explode('||', $line);
706 if (sizeof($splitedLine) == 4) {
708 $result['section'] = 'scm';
709 $result['group_id'] = $group_id;
710 $result['ref_id'] = 'browser.php?group_id='.$group_id;
711 $result['description'] = $splitedLine[2].' (commit '.$splitedLine[3].')';
712 $result['realname'] = '';
713 $splitedDate = explode(' ', $splitedLine[0]);
714 $result['activity_date'] = $splitedDate[0];
715 $result['subref_id'] = '';
716 $params['results'][] = $result;
720 $params['ids'][] = 'scm';
721 $params['texts'][] = _('SCM Git Commits');
728 // c-file-style: "bsd"