project,
$this->getScmType($request));
$scm = IDF_Scm::get($request);
$branches = $scm->getBranches();
$commit = $match[2];
if ('commit' != $scm->testHash($commit)) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::changeLog',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
$res = new Pluf_Template_ContextVars($scm->getChangeLog($commit, 25));
$scmConf = $request->conf->getVal('scm', 'git');
return Pluf_Shortcuts_RenderToResponse('source/changelog.html',
array(
'page_title' => $title,
'title' => $title,
'changes' => $res,
'commit' => $commit,
'branches' => $branches,
'scm' => $scmConf,
),
$request);
}
public $treeBase_precond = array('IDF_Precondition::accessSource');
public function treeBase($request, $match)
{
$title = sprintf(__('%1$s %2$s Source Tree'), (string) $request->project,
$this->getScmType($request));
$scm = IDF_Scm::get($request);
$commit = $match[2];
$branches = $scm->getBranches();
if ('commit' != $scm->testHash($commit)) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
$res = new Pluf_Template_ContextVars($scm->filesAtCommit($commit));
$cobject = $scm->getCommit($commit);
$tree_in = in_array($commit, $branches);
$scmConf = $request->conf->getVal('scm', 'git');
$props = null;
if ($scmConf === 'svn') {
$props = $scm->getProperties($commit);
}
return Pluf_Shortcuts_RenderToResponse('source/'.$scmConf.'/tree.html',
array(
'page_title' => $title,
'title' => $title,
'files' => $res,
'cobject' => $cobject,
'commit' => $commit,
'tree_in' => $tree_in,
'branches' => $branches,
'props' => $props,
),
$request);
}
public $tree_precond = array('IDF_Precondition::accessSource');
public function tree($request, $match)
{
$title = sprintf(__('%1$s %2$s Source Tree'), (string) $request->project,
$this->getScmType($request));
$scm = IDF_Scm::get($request);
$branches = $scm->getBranches();
$commit = $match[2];
$request_file = $match[3];
if ('commit' != $scm->testHash($commit, $request_file)) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
$request_file_info = $scm->getFileInfo($request_file, $commit);
if (!$request_file_info) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
if ($request_file_info->type != 'tree') {
$info = self::getMimeType($request_file_info->file);
if (!self::isText($info)) {
$rep = new Pluf_HTTP_Response($scm->getBlob($request_file_info, $commit),
$info[0]);
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"';
} else {
// We want to display the content of the file as text
$rep = new Pluf_HTTP_Response($scm->getBlob($request_file_info, $commit),
'text/plain');
}
return $rep;
}
$bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->file);
$page_title = $bc.' - '.$title;
$cobject = $scm->getCommit($commit);
$tree_in = in_array($commit, $branches);
$res = new Pluf_Template_ContextVars($scm->filesAtCommit($commit, $request_file));
// try to find the previous level if it exists.
$prev = split('/', $request_file);
$l = array_pop($prev);
$previous = substr($request_file, 0, -strlen($l.' '));
$scmConf = $request->conf->getVal('scm', 'git');
$props = null;
if ($scmConf === 'svn') {
$props = $scm->getProperties($commit, $request_file);
}
return Pluf_Shortcuts_RenderToResponse('source/'.$scmConf.'/tree.html',
array(
'page_title' => $page_title,
'title' => $title,
'breadcrumb' => $bc,
'files' => $res,
'commit' => $commit,
'cobject' => $cobject,
'base' => $request_file_info->file,
'prev' => $previous,
'tree_in' => $tree_in,
'branches' => $branches,
'props' => $props,
),
$request);
}
public static function makeBreadCrumb($project, $commit, $file, $sep='/')
{
$elts = split('/', $file);
$out = array();
$stack = '';
$i = 0;
foreach ($elts as $elt) {
$stack .= ($i==0) ? $elt : '/'.$elt;
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
array($project->shortname,
$commit, $stack));
$out[] = ''.Pluf_esc($elt).'';
$i++;
}
return ''.implode(''.$sep.'', $out).'';
}
public $commit_precond = array('IDF_Precondition::accessSource');
public function commit($request, $match)
{
$scm = IDF_Scm::get($request);
$commit = $match[2];
$branches = $scm->getBranches();
if ('commit' != $scm->testHash($commit)) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
$title = sprintf(__('%s Commit Details'), (string) $request->project);
$page_title = sprintf(__('%s Commit Details - %s'), (string) $request->project, $commit);
$cobject = $scm->getCommit($commit);
$diff = new IDF_Diff($cobject->changes);
$diff->parse();
$scmConf = $request->conf->getVal('scm', 'git');
return Pluf_Shortcuts_RenderToResponse('source/commit.html',
array(
'page_title' => $page_title,
'title' => $title,
'diff' => $diff,
'cobject' => $cobject,
'commit' => $commit,
'branches' => $branches,
'scm' => $scmConf,
),
$request);
}
/**
* Get a zip archive of the current commit.
*
*/
public $download_precond = array('IDF_Precondition::accessSource');
public function download($request, $match)
{
$commit = trim($match[2]);
$scm = IDF_Scm::get($request);
$branches = $scm->getBranches();
if ('commit' != $scm->testHash($commit)) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$branches[0]));
return new Pluf_HTTP_Response_Redirect($url);
}
$base = $request->project->shortname.'-'.$commit;
$cmd = $scm->getArchiveCommand($commit, $base.'/');
$rep = new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip');
$rep->headers['Content-Transfer-Encoding'] = 'binary';
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$base.'.zip"';
return $rep;
}
/**
* Find the mime type of a file.
*
* Use /etc/mime.types to find the type.
*
* @param string Filename/Filepath
* @param string Path to the mime types database ('/etc/mime.types')
* @param array Mime type found or 'application/octet-stream', basename, extension
*/
public static function getMimeType($file, $src='/etc/mime.types')
{
$mimes = preg_split("/\015\012|\015|\012/", file_get_contents($src));
$info = pathinfo($file);
if (isset($info['extension'])) {
foreach ($mimes as $mime) {
if ('#' != substr($mime, 0, 1)) {
$elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY);
if (in_array($info['extension'], $elts)) {
return array($elts[0], $info['basename'], $info['extension']);
}
}
}
} else {
// we consider that if no extension and base name is all
// uppercase, then we have a text file.
if ($info['basename'] == strtoupper($info['basename'])) {
return array('text/plain', $info['basename'], 'txt');
}
$info['extension'] = 'bin';
}
return array('application/octet-stream', $info['basename'], $info['extension']);
}
/**
* Find if a given mime type is a text file.
* This uses the output of the self::getMimeType function.
*
* @param array (Mime type, file name, extension)
* @return bool Is text
*/
public static function isText($fileinfo)
{
if (0 === strpos($fileinfo[0], 'text/')) {
return true;
}
$ext = 'mdtext php js';
return (in_array($fileinfo[2], explode(' ', $ext)));
}
/**
* Get the scm type for page title
*
* @return String
*/
private function getScmType($request)
{
return mb_convert_case($request->conf->getVal('scm', 'git'),
MB_CASE_TITLE, 'UTF-8');
}
}
function IDF_Views_Source_PrettySize($size)
{
return Pluf_Template::markSafe(str_replace(' ', ' ',
Pluf_Utils::prettySize($size)));
}