enhanced source browser to track changed paths

This commit is contained in:
hyung-hwan 2010-02-18 13:19:03 +00:00
parent 0a15131296
commit 41c025c009
8 changed files with 520 additions and 409 deletions

View File

@ -24,57 +24,7 @@ class Source extends Controller
function home ($projectid = '', $subdir = '', $rev = SVN_REVISION_HEAD)
{
return $this->folder ($projectid, $subdir, $rev);
}
function folder ($projectid = '', $path = '', $rev = SVN_REVISION_HEAD)
{
$this->load->model ('ProjectModel', 'projects');
$this->load->model ('SubversionModel', 'subversion');
$login = $this->login->getUser ();
if (CODEPOT_ALWAYS_REQUIRE_SIGNIN && $login['id'] == '')
redirect ('main/signin');
$data['login'] = $login;
$path = $this->converter->HexToAscii ($path);
if ($path == '.') $path = ''; /* treat a period specially */
$project = $this->projects->get ($projectid);
if ($project === FALSE)
{
$data['message'] = 'DATABASE ERROR';
$this->load->view ($this->VIEW_ERROR, $data);
}
else if ($project === NULL)
{
$data['message'] = "NO SUCH PROJECT - $projectid";
$this->load->view ($this->VIEW_ERROR, $data);
}
else
{
$files = $this->subversion->getList ($projectid, $path, $rev);
if ($files === FALSE)
{
$data['message'] = 'Failed to get file list';
$this->load->view ($this->VIEW_ERROR, $data);
}
else
{
$data['project'] = $project;
$data['folder'] = $path;
$data['files'] = $files;
$data['revision'] = $rev;
$data['prev_revision'] =
$this->subversion->getPrevRev ($projectid, $path, $rev);
$data['next_revision'] =
$this->subversion->getNextRev ($projectid, $path, $rev);
$this->load->view ($this->VIEW_FOLDER, $data);
}
}
return $this->file ($projectid, $subdir, $rev);
}
function file ($projectid, $path = '', $rev = SVN_REVISION_HEAD)
@ -106,28 +56,10 @@ class Source extends Controller
$file = $this->subversion->getFile ($projectid, $path, $rev);
if ($file === FALSE)
{
$files = $this->subversion->getList ($projectid, $path, $rev);
if ($files === FALSE)
{
$data['message'] = 'Failed to get file';
$this->load->view ($this->VIEW_ERROR, $data);
}
else
{
$data['project'] = $project;
$data['folder'] = $path;
$data['files'] = $files;
$data['revision'] = $rev;
$data['prev_revision'] =
$this->subversion->getPrevRev ($projectid, $path, $rev);
$data['next_revision'] =
$this->subversion->getNextRev ($projectid, $path, $rev);
$this->load->view ($this->VIEW_FOLDER, $data);
}
$data['message'] = 'Failed to get file';
$this->load->view ($this->VIEW_ERROR, $data);
}
else
else if ($file['type'] == 'file')
{
$head_rev = $this->subversion->getHeadRev ($projectid, $path);
if ($head_rev === FALSE)
@ -144,12 +76,26 @@ class Source extends Controller
$projectid, $path, $file['created_rev']);
$data['project'] = $project;
$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['headpath'] = $path;
$data['file'] = $file;
$data['revision'] = $rev;
$this->load->view ($this->VIEW_FILE, $data);
}
}
else
{
$data['project'] = $project;
$data['headpath'] = $path;
$data['file'] = $file;
$data['revision'] = $rev;
$data['prev_revision'] =
$this->subversion->getPrevRev ($projectid, $path, $rev);
$data['next_revision'] =
$this->subversion->getNextRev ($projectid, $path, $rev);
$this->load->view ($this->VIEW_FOLDER, $data);
}
}
}
@ -202,7 +148,8 @@ class Source extends Controller
$projectid, $path, $file['created_rev']);
$data['project'] = $project;
$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['headpath'] = $path;
$data['file'] = $file;
$data['revision'] = $rev;
$this->load->view ($this->VIEW_BLAME, $data);
@ -211,7 +158,7 @@ class Source extends Controller
}
}
function history ($type, $projectid, $path = '', $rev = SVN_REVISION_HEAD)
function history ($projectid, $path = '', $rev = SVN_REVISION_HEAD)
{
$this->load->model ('ProjectModel', 'projects');
$this->load->model ('SubversionModel', 'subversion');
@ -245,10 +192,8 @@ class Source extends Controller
}
else
{
$data['type'] = $type;
$data['project'] = $project;
//$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['folder'] = $path;
$data['fullpath'] = $path;
$data['file'] = $file;
$data['revision'] = $rev;
@ -262,7 +207,7 @@ class Source extends Controller
}
}
function revision ($type, $projectid, $path, $rev = SVN_REVISION_HEAD)
function revision ($projectid, $path, $rev = SVN_REVISION_HEAD)
{
$this->load->model ('ProjectModel', 'projects');
$this->load->model ('SubversionModel', 'subversion');
@ -296,10 +241,8 @@ class Source extends Controller
}
else
{
$data['type'] = $type;
$data['project'] = $project;
//$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['folder'] = $path;
$data['headpath'] = $path;
$data['file'] = $file;
$data['revision'] = $rev;
@ -313,7 +256,7 @@ class Source extends Controller
}
}
function diff ($projectid, $path, $rev1 = SVN_REVISION_HEAD, $rev2 = SVN_REVISION_PREV)
function diff ($projectid, $path, $rev1 = SVN_REVISION_HEAD, $rev2 = SVN_REVISION_HEAD)
{
$this->load->model ('ProjectModel', 'projects');
$this->load->model ('SubversionModel', 'subversion');
@ -356,10 +299,11 @@ class Source extends Controller
$this->subversion->getNextRev ($projectid, $path, $file['against']['created_rev']);
$data['project'] = $project;
$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['file'] = $file;
//$data['folder'] = substr ($path, 0, strrpos($path, '/'));
$data['headpath'] = $path;
$data['revision1'] = $rev1;
$data['revision2'] = $rev2;
$data['file'] = $file;
$this->load->view ($this->VIEW_DIFF, $data);
}
}

View File

@ -7,85 +7,135 @@ class SubversionModel extends Model
parent::Model ();
}
function getList ($projectid, $subdir = '', $rev = SVN_REVISION_HEAD, $recurse = FALSE)
function getFile ($projectid, $path, $rev = SVN_REVISION_HEAD)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid;
if ($subdir != '') $path .= "/{$subdir}";
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$list = @svn_ls ($path, $rev, $recurse);
if ($list === FALSE) return FALSE;
$info = @svn_info ($url, FALSE, $rev);
if ($info === FALSE || count($info) != 1) return FALSE;
return $list;
if ($info[0]['kind'] == SVN_NODE_FILE)
{
$lsinfo = @svn_ls ($url, $rev, FALSE, TRUE);
if ($lsinfo === FALSE) return FALSE;
if (array_key_exists ($info[0]['path'], $lsinfo) === FALSE) return FALSE;
$fileinfo = $lsinfo[$info[0]['path']];
$str = @svn_cat ($url, $rev);
if ($str === FALSE) return FALSE;
$fileinfo['fullpath'] = substr (
$info[0]['url'], strlen($info[0]['repos']));
$fileinfo['content'] = $str;
return $fileinfo;
}
else if ($info[0]['kind'] == SVN_NODE_DIR)
{
$list = @svn_ls ($url, $rev, FALSE, TRUE);
if ($list === FALSE) return FALSE;
$fileinfo['fullpath'] = substr (
$info[0]['url'], strlen($info[0]['repos']));
$fileinfo['name'] = $info[0]['path'];
$fileinfo['type'] = 'dir';
$fileinfo['size'] = 0;
$fileinfo['created_rev'] = $info[0]['revision'];
$fileinfo['last_author'] = $info[0]['last_changed_rev'];
$fileinfo['content'] = $list;
return $fileinfo;
}
return FALSE;
}
function getFile ($projectid, $file, $rev = SVN_REVISION_HEAD)
function getBlame ($projectid, $path, $rev = SVN_REVISION_HEAD)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_ls ($path, $rev, FALSE);
if ($info === FALSE) return FALSE;
$info = @svn_info ($url, FALSE, $rev);
if ($info === FALSE || count($info) != 1) return FALSE;
$last = substr(strrchr($path, '/'), 1);
if ($last === FALSE) $last = '';
if ($info[0]['kind'] != SVN_NODE_FILE) return FALSE;
if (array_key_exists ($last, $info) === FALSE) return FALSE;
$fileinfo = $info[$last];
$lsinfo = @svn_ls ($url, $rev, FALSE, TRUE);
if ($lsinfo === FALSE) return FALSE;
$str = @svn_cat ($path, $rev);
if (array_key_exists ($info[0]['path'], $lsinfo) === FALSE) return FALSE;
$fileinfo = $lsinfo[$info[0]['path']];
$str = @svn_blame ($url, $rev);
if ($str === FALSE) return FALSE;
$fileinfo['fullpath'] = substr (
$info[0]['url'], strlen($info[0]['repos']));
$fileinfo['content'] = $str;
return $fileinfo;
}
function getBlame ($projectid, $file, $rev = SVN_REVISION_HEAD)
function getHistory ($projectid, $path, $rev = SVN_REVISION_HEAD)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_ls ($path, $rev, FALSE);
if ($info === FALSE) return FALSE;
$info = @svn_info ($url, FALSE, $rev);
if ($info === FALSE || count($info) != 1) return FALSE;
$last = substr(strrchr($path, '/'), 1);
if ($last === FALSE) $last = '';
if ($info[0]['kind'] == SVN_NODE_FILE)
{
$lsinfo = @svn_ls ($url, $rev, FALSE, TRUE);
if ($lsinfo === FALSE) return FALSE;
if (array_key_exists ($last, $info) === FALSE) return FALSE;
$fileinfo = $info[$last];
if (array_key_exists ($info[0]['path'], $lsinfo) === FALSE) return FALSE;
$fileinfo = $lsinfo[$info[0]['path']];
}
else if ($info[0]['kind'] == SVN_NODE_DIR)
{
$fileinfo['fullpath'] = substr (
$info[0]['url'], strlen($info[0]['repos']));
$fileinfo['name'] = $info[0]['path'];
$fileinfo['type'] = 'dir';
$fileinfo['size'] = 0;
$fileinfo['created_rev'] = $info[0]['revision'];
$fileinfo['last_author'] = $info[0]['last_changed_rev'];
}
else return FALSE;
$str = @svn_blame ($path, $rev);
if ($str === FALSE) return FALSE;
$fileinfo['content'] = $str;
return $fileinfo;
}
function getHistory ($projectid, $file, $rev = SVN_REVISION_HEAD)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$last = substr(strrchr($path, '/'), 1);
if ($last === FALSE) $last = '';
/* set the file name to the information array */
$fileinfo['name'] = $last;
$log = @svn_log ($path, 1, $rev, 0, SVN_DISCOVER_CHANGED_PATHS);
$log = @svn_log ($url, 1, $rev, 0, SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return FALSE;
$fileinfo['history'] = $log;
return $fileinfo;
}
function getRevHistory ($projectid, $file, $rev)
function getRevHistory ($projectid, $path, $rev)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$last = substr(strrchr($path, '/'), 1);
if ($last === FALSE) $last = '';
$info = @svn_info ($url, FALSE, $rev);
if ($info === FALSE || count($info) != 1) return FALSE;
/* set the file name to the information array */
$fileinfo['name'] = $last;
if ($info[0]['kind'] == SVN_NODE_FILE)
{
$lsinfo = @svn_ls ($url, $rev, FALSE, TRUE);
if ($lsinfo === FALSE) return FALSE;
$log = @svn_log ($path, $rev, $rev, 1, SVN_DISCOVER_CHANGED_PATHS);
if (array_key_exists ($info[0]['path'], $lsinfo) === FALSE) return FALSE;
$fileinfo = $lsinfo[$info[0]['path']];
}
else if ($info[0]['kind'] == SVN_NODE_DIR)
{
$fileinfo['fullpath'] = substr (
$info[0]['url'], strlen($info[0]['repos']));
$fileinfo['name'] = $info[0]['path'];
$fileinfo['type'] = 'dir';
$fileinfo['size'] = 0;
$fileinfo['created_rev'] = $info[0]['revision'];
$fileinfo['last_author'] = $info[0]['last_changed_rev'];
}
else return FALSE;
$log = @svn_log ($url, $rev, $rev, 1, SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return FALSE;
if (count($log) != 1) return FALSE;
@ -334,96 +384,163 @@ class SubversionModel extends Model
return $listing;
}
function getDiff ($projectid, $file, $rev1, $rev2)
//
// Given a path name at the HEAD revision, it compares the file
// between two revisions given. The actual path name at a given
// revision can be different from the path name at the HEAD revision.
//
// $file - path name at the HEAD revision
// $rev1 - new revision number
// $rev2 - old revision number
//
function getDiff ($projectid, $path, $rev1, $rev2)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_ls ($path, $rev1, FALSE);
if ($info === FALSE) return FALSE;
$lsinfo1 = @svn_ls ($url, $rev1, FALSE, TRUE);
if ($lsinfo1 === FALSE || count($lsinfo1) != 1) return FALSE;
$last = substr(strrchr($path, '/'), 1);
if ($last === FALSE) $last = '';
// the check above guarantees that the foreach block below
// is executed only once.
foreach ($lsinfo1 as $key => $value)
{
if ($value['type'] != 'file') return FALSE;
$rev1 = $value['created_rev'];
$fileinfo = $value;
}
if (array_key_exists ($last, $info) === FALSE) return FALSE;
$fileinfo = $info[$last];
$rev1 = $info[$last]['created_rev'];
$fileinfo['head_name'] = $path;
if ($rev2 <= 0)
{
/*
$log = @svn_log ($path, $rev1, SVN_REVISION_INITIAL, 2);
// get two log entries including the new revision
$log = @svn_log (
$url, $rev1, SVN_REVISION_INITIAL, 2,
SVN_OMIT_MESSAGES | SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return FALSE;
if (count($log) < 2) return FALSE;
$rev2 = $log[1]['rev'];
*/
$rev2 = $rev1 - 1;
if ($rev2 <= 0) $rev2 = $rev1;
$rev2 = $log[(count($log) <= 1)? 0:1]['rev'];
}
$info2 = @svn_ls ($path, $rev2, FALSE);
if ($info2 === FALSE)
$lsinfo2 = @svn_ls ($url, $rev2, FALSE, TRUE);
if ($lsinfo2 === FALSE || count($lsinfo2) != 1) return FALSE;
// the check above guarantees the foreach block below
// is executed only once.
foreach ($lsinfo2 as $key => $value)
{
$rev2 = $rev1;
$info2 = @svn_ls ($path, $rev2, FALSE);
if ($info2 === FALSE) return FALSE;
if ($value['type'] != 'file') return FALSE;
$rev2 = $value['created_rev'];
$fileinfo['against'] = $value;
}
if (array_key_exists ($last, $info2) === FALSE) return FALSE;
$rev2 = $info2[$last]['created_rev'];
// let's get the actual URL for each revision.
// the actual URLs may be different from $url
// if the file has been changed.
$info1 = @svn_info ($url, FALSE, $rev1);
if ($info1 === FALSE || count($info1) != 1) return FALSE;
if ($info1[0]['kind'] != SVN_NODE_FILE) return FALSE;
$info2 = @svn_info ($url, FALSE, $rev2);
if ($info2 === FALSE || count($info1) != 1) return FALSE;
if ($info2[0]['kind'] != SVN_NODE_FILE) return FALSE;
list($diff, $errors) = @svn_diff ($path, $rev2, $path, $rev1);
// get the difference with the actual URLs
list($diff, $errors) = @svn_diff (
$info2[0]['url'], $info2[0]['revision'],
$info1[0]['url'], $info1[0]['revision']);
if (!$diff) return FALSE;
/*
## Sample svn_info() array ##
[0] => Array
(
[path] => codepot.sql
[url] => file:///svn/test/codepot.sql
[revision] => 27
[kind] => 1
[repos] => file:///svn/test
[last_changed_rev] => 27
[last_changed_date] => 2010-02-18T01:53:13.076062Z
[last_changed_author] => hyunghwan
)
*/
$fileinfo['fullpath'] = substr (
$info1[0]['url'], strlen($info1[0]['repos']));
$fileinfo['against']['fullpath'] = substr (
$info2[0]['url'], strlen($info2[0]['repos']));
fclose($errors);
$fileinfo['content'] = $this->_get_diff ($diff, FALSE, FALSE);
fclose ($diff);
/*
print_r ($info[$last]);
print_r ($info2[$last]);
*/
$fileinfo['against'] = $info2[$last];
return $fileinfo;
}
function getPrevRev ($projectid, $file, $rev)
function getPrevRev ($projectid, $path, $rev)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_log ($path, $rev, SVN_REVISION_INITIAL, 2, SVN_OMIT_MESSAGES);
if ($info === FALSE) return $rev;
$log = @svn_log (
$url, $rev, SVN_REVISION_INITIAL, 2,
SVN_OMIT_MESSAGES | SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return $rev;
$count = count($info);
$count = count($log);
if ($count <= 0) return $rev;
if ($count == 1) return $info[0]['rev'];
if ($count == 1) return $log[0]['rev'];
return $info[1]['rev'];
return $log[1]['rev'];
}
function getNextRev ($projectid, $file, $rev)
function getNextRev ($projectid, $path, $rev)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_log ($path, SVN_REVISION_HEAD, $rev, 0, SVN_OMIT_MESSAGES);
if ($info === FALSE) return $rev;
$log = @svn_log (
$url, SVN_REVISION_HEAD, $rev, 0,
SVN_OMIT_MESSAGES | SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return $rev;
$count = count($info);
$count = count($log);
if ($count <= 0) return $rev;
if ($count == 1) return $info[0]['rev'];
if ($count == 1) return $log[0]['rev'];
return $info[$count-2]['rev'];
//
// r22 /usr/lib/a.c updated a.c
// r21 /usr/lib/a.c moved /lib to /usr/lib
// r10 /lib/a.c updated a.c
// r5 /lib/a.c added a.c
// ------------------------------------------------------
// subversion does not a.c for r21 to show.
// the same thing can happen if the file is just renamed.
// make best effort to find the revision with change.
//
for ($count = $count - 2; $count >= 0; $count--)
{
$info = svn_info ($url, FALSE, $log[$count]['rev']);
if ($info === FALSE) return FALSE;
if ($info[0]['last_changed_rev'] > $rev)
{
return $info[0]['revision'];
}
}
return $rev;
}
function getHeadRev ($projectid, $file)
function getHeadRev ($projectid, $path)
{
$path = 'file:///' . CODEPOT_SVNREPO_DIR . '/' . $projectid . '/' . $file;
$url = 'file:///'.CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}";
$info = @svn_log ($path, SVN_REVISION_HEAD, SVN_REVISION_INITIAL, 1, SVN_OMIT_MESSAGES);
if ($info === FALSE) return FALSE;
if (count($info) != 1) return FALSE;
return $info[0]['rev'];
$log = @svn_log (
$url, SVN_REVISION_HEAD, SVN_REVISION_INITIAL, 1,
SVN_OMIT_MESSAGES | SVN_DISCOVER_CHANGED_PATHS);
if ($log === FALSE) return FALSE;
if (count($log) != 1) return FALSE;
return $log[0]['rev'];
}
}

View File

@ -39,73 +39,75 @@ $this->load->view (
<div class="title" id="project_source_blame_mainarea_title">
<?php
if ($revision <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
//$revreq = ($file['created_rev'] == $file['head_rev'])? '': "/{$file['created_rev']}";
//$revreqroot = ($revreq == '')? '': ('/' . $this->converter->AsciiToHex ('.') . $revreq);
$revreq = "/{$revision}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
if ($revision <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
$revreq = "/{$file['created_rev']}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
print anchor (
"/source/folder/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
print anchor (
"/source/file/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
if ($folder != '')
{
$exps = explode ('/', $folder);
$exps = explode ('/', $headpath);
$expsize = count($exps);
$par = '';
for ($i = 1; $i < $expsize; $i++)
{
print '/';
$par .= '/' . $exps[$i];
$hexpar = $this->converter->AsciiToHex ($par);
print anchor (
"source/folder/{$project->id}/{$hexpar}{$revreq}",
htmlspecialchars($exps[$i]));
$xpar = $this->converter->AsciiToHex ($par);
print '/';
if ($i == $expsize - 1)
{
print anchor (
"source/blame/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
else
{
print anchor (
"source/file/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
}
}
print '/';
$par = $this->converter->AsciiTohex ("{$folder}/{$file['name']}");
print anchor (
"/source/blame/{$project->id}/{$par}{$revreq}",
htmlspecialchars($file['name']));
if ($headpath != $file['fullpath'])
{
print ' - ';
print htmlspecialchars($file['fullpath']);
}
?>
</div> <!-- project_source_blame_mainarea_title -->
<div class="menu" id="project_source_blame_mainarea_menu">
<?php
$par = $this->converter->AsciiToHex ("{$folder}/{$file['name']}");
$xpar = $this->converter->AsciiToHex ($headpath);
if ($file['created_rev'] != $file['head_rev'])
{
print anchor ("source/file/{$project->id}/${par}", $this->lang->line('Head revision'));
print anchor ("source/file/{$project->id}/${xpar}", $this->lang->line('Head revision'));
print ' | ';
}
print anchor ("source/file/{$project->id}/${par}{$revreq}", $this->lang->line('Details'));
print anchor ("source/file/{$project->id}/${xpar}{$revreq}", $this->lang->line('Details'));
print ' | ';
print anchor ("source/diff/{$project->id}/{$par}{$revreq}", $this->lang->line('Difference'));
print anchor ("source/diff/{$project->id}/{$xpar}{$revreq}", $this->lang->line('Difference'));
print ' | ';
print anchor ("source/history/file/{$project->id}/{$par}", $this->lang->line('History'));
print anchor ("source/history/{$project->id}/{$xpar}", $this->lang->line('History'));
?>
</div> <!-- project_source_blame_mainarea_menu -->
<div class="infostrip">
<?=anchor ("source/file/{$project->id}/${par}/{$file['prev_rev']}", '<<')?>
<?=anchor ("source/file/{$project->id}/${xpar}/{$file['prev_rev']}", '<<')?>
<?=$this->lang->line('Revision')?>: <?=$file['created_rev']?>
<?=anchor ("source/file/{$project->id}/${par}/{$file['next_rev']}", '>>')?> |
<?=anchor ("source/file/{$project->id}/${xpar}/{$file['next_rev']}", '>>')?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($file['last_author'])?> |
<?=$this->lang->line('Size')?>: <?=$file['size']?> |
<?=$this->lang->line('Last updated on')?>: <?=$file['time']?>
@ -134,8 +136,8 @@ for ($i = 0; $i < $len; $i++)
$rev = $line['rev'];
$rev_padded = str_pad ($rev, 6, ' ', STR_PAD_LEFT);
$par = $this->converter->AsciiTohex ("{$folder}/{$file['name']}");
$rev_padded = anchor ("/source/blame/{$project->id}/{$par}/{$rev}", $rev_padded);
$xpar = $this->converter->AsciiTohex ($headpath);
$rev_padded = anchor ("/source/blame/{$project->id}/{$xpar}/{$rev}", $rev_padded);
}
else
{

View File

@ -39,65 +39,57 @@ $this->load->view (
<div class="title" id="project_source_diff_mainarea_title">
<?php
$xpar = '/source/folder/' . $project->id;
print anchor ($xpar, htmlspecialchars($project->name));
if ($folder != '')
{
$exps = explode ('/', $folder);
if ($revision1 <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
$revreq = "/{$file['created_rev']}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
print anchor (
"/source/file/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
$exps = explode ('/', $headpath);
$expsize = count($exps);
$par = '';
for ($i = 1; $i < $expsize; $i++)
{
$par .= '/' . $exps[$i];
$hexpar = $this->converter->AsciiToHex ($par);
$par .= "/{$exps[$i]}";
$xpar = $this->converter->AsciiToHex ($par);
$xpar = "source/file/{$project->id}/{$xpar}{$revreq}";
print '/';
$xpar = 'source/folder/' . $project->id . '/' . $hexpar;
if ($revision1 != SVN_REVISION_HEAD) $xpar .= '/' . $revision1;
print anchor ($xpar, htmlspecialchars($exps[$i]));
}
}
$par = $folder . '/' . $file['name'];
$par = $this->converter->AsciiTohex ($par);
print '/';
$xpar = '/source/file/' . $project->id . '/' . $par;
if ($revision1 != SVN_REVISION_HEAD) $xpar .= '/' . $revision1;
print anchor ($xpar, htmlspecialchars($file['name']));
?>
</div> <!-- project_source_diff_mainarea_title -->
<div class="menu" id="project_source_diff_mainarea_menu">
<?php
$par = $folder . '/' . $file['name'];
$par = $this->converter->AsciiTohex ($par);
$xdetails = "source/file/{$project->id}/{$par}";
$xblame = "source/blame/{$project->id}/{$par}";
if ($revision1 != SVN_REVISION_HEAD)
{
$xdetails .= "/{$revision1}";
$xblame .= "/{$revision1}";
}
print anchor ($xdetails, $this->lang->line('Details'));
print ' | ';
print anchor ($xblame, $this->lang->line('Blame'));
print ' | ';
print anchor ("source/history/file/{$project->id}/{$par}", $this->lang->line('History'));
$xpar = $this->converter->AsciiTohex ($headpath);
print anchor (
"source/file/{$project->id}/{$xpar}{$revreq}",
$this->lang->line('Details'));
print ' | ';
print anchor (
"source/blame/{$project->id}/{$xpar}{$revreq}",
$this->lang->line('Blame'));
print ' | ';
print anchor (
"source/history/file/{$project->id}/{$xpar}",
$this->lang->line('History'));
?>
</div> <!-- project_source_diff_mainarea_menu -->
<div class="infostrip" id="project_source_diff_mainarea_infostrip">
<?=$this->lang->line('Revision')?>: <?=$file['created_rev']?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($file['last_author'])?> |
<?=$this->lang->line('Size')?>: <?=$file['size']?> |
<?=$this->lang->line('Last updated on')?>: <?=$file['time']?>
</div>
<?php
$fileext = substr(strrchr($file['name'], '.'), 1);
if ($fileext == "") $fileext = "html"
$fileext = substr(strrchr($file['name'], '.'), 1);
if ($fileext == "") $fileext = "html"
?>
<div id="project_source_diff_mainarea_result">
@ -115,7 +107,7 @@ if ($fileext == "") $fileext = "html"
$currev = $file['created_rev'];
$prevrev = $file['against']['prev_rev'];
$prevanc = "source/diff/{$project->id}/{$par}/{$currev}/{$prevrev}";
$prevanc = "source/diff/{$project->id}/{$xpar}/{$currev}/{$prevrev}";
print anchor ($prevanc, '<<');
print '&nbsp;&nbsp;&nbsp;';
@ -125,7 +117,7 @@ if ($fileext == "") $fileext = "html"
$currev = $file['created_rev'];
$nextrev = $file['against']['next_rev'];
$nextanc = "source/diff/{$project->id}/{$par}/{$currev}/{$nextrev}";
$nextanc = "source/diff/{$project->id}/{$xpar}/{$currev}/{$nextrev}";
print '&nbsp;&nbsp;&nbsp;';
print anchor ($nextanc, '>>');
@ -135,7 +127,7 @@ if ($fileext == "") $fileext = "html"
$currev = $file['against']['created_rev'];
$prevrev = $file['prev_rev'];
$prevanc = "source/diff/{$project->id}/{$par}/{$prevrev}/{$currev}";
$prevanc = "source/diff/{$project->id}/{$xpar}/{$prevrev}/{$currev}";
print anchor ($prevanc, '<<');
print '&nbsp;&nbsp;&nbsp;';
@ -145,13 +137,33 @@ if ($fileext == "") $fileext = "html"
$currev = $file['against']['created_rev'];
$nextrev = $file['next_rev'];
$nextanc = "source/diff/{$project->id}/{$par}/{$nextrev}/{$currev}";
$nextanc = "source/diff/{$project->id}/{$xpar}/{$nextrev}/{$currev}";
print '&nbsp;&nbsp;&nbsp;';
print anchor ($nextanc, '>>');
print '</th>';
print '</tr>';
if ($headpath != $file['fullpath'] ||
$headpath != $file['against']['fullpath'])
{
print '<tr>';
print '<th>';
print anchor (
"source/file/{$project->id}/{$xpar}/{$file['against']['created_rev']}",
htmlspecialchars ($file['against']['fullpath']));
print '</th>';
print '<th>';
print anchor (
"source/file/{$project->id}/{$xpar}/{$file['created_rev']}",
htmlspecialchars ($file['fullpath']));
print '</th>';
print '</tr>';
}
if (empty($file['content']))
{
print '<tr>';

View File

@ -39,74 +39,76 @@ $this->load->view (
<div class="title" id="project_source_file_mainarea_title">
<?php
if ($revision <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
//$revreq = ($file['created_rev'] == $file['head_rev'])? '': "/{$file['created_rev']}";
//$revreqroot = ($revreq == '')? '': ('/' . $this->converter->AsciiToHex ('.') . $revreq);
$revreq = "/{$revision}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
if ($revision <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
$revreq = "/{$file['created_rev']}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
print anchor (
"/source/folder/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
print anchor (
"/source/file/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
if ($folder != '')
{
$exps = explode ('/', $folder);
$exps = explode ('/', $headpath);
$expsize = count($exps);
$par = '';
for ($i = 1; $i < $expsize; $i++)
{
print '/';
$par .= '/' . $exps[$i];
$hexpar = $this->converter->AsciiToHex ($par);
$xpar = $this->converter->AsciiToHex ($par);
print '/';
print anchor (
"source/folder/{$project->id}/{$hexpar}{$revreq}",
"source/file/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
}
print '/';
$par = $this->converter->AsciiTohex ("{$folder}/{$file['name']}");
print anchor (
"/source/file/{$project->id}/{$par}{$revreq}",
htmlspecialchars($file['name']));
if ($headpath != $file['fullpath'])
{
print ' - ';
print htmlspecialchars($file['fullpath']);
}
?>
</div> <!-- project_source_file_mainarea_title -->
<div class="menu" id="project_source_file_mainarea_menu">
<?php
$par = $this->converter->AsciiToHex ("{$folder}/{$file['name']}");
$xpar = $this->converter->AsciiToHex ($headpath);
if ($file['created_rev'] != $file['head_rev'])
{
print anchor ("source/file/{$project->id}/${par}", $this->lang->line('Head revision'));
if ($file['created_rev'] != $file['head_rev'])
{
print anchor (
"source/file/{$project->id}/${xpar}",
$this->lang->line('Head revision'));
print ' | ';
}
print anchor (
"source/blame/{$project->id}/${xpar}{$revreq}",
$this->lang->line('Blame'));
print ' | ';
}
print anchor ("source/blame/{$project->id}/${par}{$revreq}", $this->lang->line('Blame'));
print ' | ';
print anchor ("source/diff/{$project->id}/{$par}{$revreq}", $this->lang->line('Difference'));
print ' | ';
print anchor ("source/history/file/{$project->id}/{$par}", $this->lang->line('History'));
print anchor (
"source/diff/{$project->id}/{$xpar}{$revreq}",
$this->lang->line('Difference'));
print ' | ';
print anchor (
"source/history/{$project->id}/{$xpar}",
$this->lang->line('History'));
?>
</div> <!-- project_source_file_mainarea_menu -->
<div class="infostrip" id="project_source_file_mainarea_infostrip">
<?=anchor ("source/file/{$project->id}/${par}/{$file['prev_rev']}", '<<')?>
<?=$this->lang->line('Revision')?>: <?=$file['created_rev']?>
<?=anchor ("source/file/{$project->id}/${par}/{$file['next_rev']}", '>>')?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($file['last_author'])?> |
<?=$this->lang->line('Size')?>: <?=$file['size']?> |
<?=$this->lang->line('Last updated on')?>: <?=$file['time']?>
<?=anchor ("source/file/{$project->id}/${xpar}/{$file['prev_rev']}", '<<')?>
<?=$this->lang->line('Revision')?>: <?=$file['created_rev']?>
<?=anchor ("source/file/{$project->id}/${xpar}/{$file['next_rev']}", '>>')?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($file['last_author'])?> |
<?=$this->lang->line('Size')?>: <?=$file['size']?> |
<?=$this->lang->line('Last updated on')?>: <?=$file['time']?>
</div>
<div id="project_source_file_mainarea_result">

View File

@ -61,11 +61,11 @@ $this->load->view (
// print the main anchor for the root folder.
// let the anchor text be the project name.
print anchor (
"/source/folder/{$project->id}{$revreqroot}",
"/source/file/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
// explode non-root folder parts to anchors
$exps = explode ('/', $folder);
$exps = explode ('/', $headpath);
$expsize = count($exps);
$par = '';
for ($i = 1; $i < $expsize; $i++)
@ -74,9 +74,15 @@ $this->load->view (
$par .= '/' . $exps[$i];
$xpar = $this->converter->AsciiToHex ($par);
print anchor (
"source/folder/{$project->id}/{$xpar}{$revreq}",
"source/file/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
if ($headpath != $file['fullpath'])
{
print ' - ';
print htmlspecialchars ($file['fullpath']);
}
?>
</div>
@ -92,23 +98,23 @@ $this->load->view (
return ($a['type'] == 'dir')? -1: 1;
}
if (count($files) <= 0)
if (count($file['content']) <= 0)
{
print $this->lang->line('MSG_NO_SOURCE_AVAIL');
}
else
{
print '<div class="menu" id="project_source_folder_mainarea_menu">';
$xpar = $this->converter->AsciiTohex ($folder);
$xpar = $this->converter->AsciiTohex ($headpath);
if ($revision > 0 && $revision < $next_revision)
{
print anchor ("source/folder/{$project->id}", $this->lang->line('Head revision'));
print anchor ("source/file/{$project->id}", $this->lang->line('Head revision'));
print ' | ';
}
print anchor ("source/history/folder/{$project->id}/{$xpar}", $this->lang->line('History'));
print anchor ("source/history/{$project->id}/{$xpar}", $this->lang->line('History'));
print '</div>';
usort ($files, 'comp_files');
usort ($file['content'], 'comp_files');
print '<div id="project_source_folder_mainarea_result">';
print '<table id="project_source_folder_mainarea_result_table">';
@ -124,9 +130,9 @@ $this->load->view (
$rowclasses = array ('even', 'odd');
$rownum = 0;
foreach ($files as $f)
foreach ($file['content'] as $f)
{
$fullpath = $folder . '/' . $f['name'];
$fullpath = $headpath . '/' . $f['name'];
$rowclass = $rowclasses[++$rownum % 2];
if ($f['type'] === 'dir')
@ -136,7 +142,7 @@ $this->load->view (
print "<tr class='{$rowclass}'>";
print '<td>';
print anchor (
"source/folder/{$project->id}/{$hexpath}{$revreq}",
"source/file/{$project->id}/{$hexpath}{$revreq}",
htmlspecialchars($f['name']));
print '</td>';
print '<td>';

View File

@ -29,12 +29,6 @@ $this->load->view (
<!---------------------------------------------------------------------------->
<div class="sidebar" id="project_source_history_sidebar">
</div> <!-- project_source_history_sidebar -->
<!---------------------------------------------------------------------------->
<div class="mainarea" id="project_source_history_mainarea">
<div class="title" id="project_source_history_mainarea_title">
@ -50,13 +44,13 @@ $this->load->view (
$revreqroot = '/' . $this->converter->AsciiToHex('.') . $revreq;
}
// print the anchor for the root folder with a project name
// print the anchor for the root nolder with a project name
print anchor (
"/source/history/folder/{$project->id}{$revreqroot}",
"/source/history/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
// explodes part of the folder name into an array
$exps = explode ('/', $folder);
// explodes part of the full path name into an array
$exps = explode ('/', $fullpath);
$expsize = count($exps);
$par = '';
// print anchors pointing to each part
@ -66,34 +60,33 @@ $this->load->view (
$par .= '/' . $exps[$i];
$xpar = $this->converter->AsciiToHex ($par);
print anchor (
"source/history/folder/{$project->id}/{$xpar}{$revreq}",
"source/history/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
?>
</div>
<div class="menu" id="project_source_history_mainarea_menu">
<!--
<?php
/* the menu here prints links to the lastest revision */
if ($type == 'folder')
$par = $this->converter->AsciiTohex ($fullpath);
print anchor (
"source/file/{$project->id}/{$par}",
$this->lang->line('Details'));
/*
if (...)
{
$par = $this->converter->AsciiTohex ($folder);
$xpar = "source/folder/{$project->id}/{$par}";
print anchor ($xpar, $this->lang->line('Folder'));
}
else
{
$par = $this->converter->AsciiTohex ($folder);
$xpar = "source/file/{$project->id}/{$par}";
print anchor ($xpar, $this->lang->line('Details'));
print ' | ';
$xpar = "source/blame/{$project->id}/{$par}";
print anchor ($xpar, $this->lang->line('Blame'));
print ' | ';
$xpar = "source/diff/{$project->id}/{$par}";
print anchor ($xpar, $this->lang->line('Difference'));
}
} */
?>
-->
</div> <!-- project_source_history_mainarea_menu -->
<div id="project_source_history_mainarea_result">
@ -103,13 +96,13 @@ $this->load->view (
<th><?=$this->lang->line('Author')?></th>
<th><?=$this->lang->line('Date')?></th>
<th><?=$this->lang->line('Message')?></th>
<th></th>
<?php if ($file['type'] == 'file') print '<th></th>'; ?>
</tr>
<?php
$rowclasses = array ('even', 'odd');
$history = $file['history'];
$history_count = count($history);
$curfolder = $folder;
$curfullpath = $fullpath;
for ($i = $history_count; $i > 0; )
{
$h = $history[--$i];
@ -118,14 +111,10 @@ $this->load->view (
print "<tr class='{$rowclass}'>";
print '<td>';
//
// it seems the history can be retrieved only from the latest name */
//
$xfolder = $this->converter->AsciiToHex(($folder == '')? '.': $folder);
if ($type == 'folder')
print anchor ("/source/revision/{$type}/{$project->id}/{$xfolder}/{$h['rev']}", $h['rev']);
else
print anchor ("/source/{$type}/{$project->id}/{$xfolder}/{$h['rev']}", $h['rev']);
$xfullpath = $this->converter->AsciiToHex (
($fullpath == '')? '.': $fullpath);
print anchor ("/source/file/{$project->id}/{$xfullpath}/{$h['rev']}", $h['rev']);
print '</td>';
print '<td>';
@ -143,26 +132,24 @@ $this->load->view (
print '</pre>';
print '</td>';
print '<td>';
//
// the actual folder or file contents must be accessed with the name
// at a particular revision.
//
$xfolder = $this->converter->AsciiToHex(($curfolder == '')? '.': $curfolder);
if ($type == 'folder')
if ($file['type'] == 'file')
{
print anchor ("/source/folder/{$project->id}/{$xfolder}/{$h['rev']}",
$this->lang->line('Folder'));
}
else
{
print anchor ("/source/blame/{$project->id}/{$xfolder}/{$h['rev']}",
print '<td>';
print anchor ("/source/blame/{$project->id}/{$xfullpath}/{$h['rev']}",
$this->lang->line('Blame'));
print ' ';
print anchor ("/source/diff/{$project->id}/{$xfolder}/{$h['rev']}",
print anchor ("/source/diff/{$project->id}/{$xfullpath}/{$h['rev']}",
$this->lang->line('Difference'));
print '</td>';
}
else if ($file['type'] == 'dir')
{
print '<td>';
print anchor ("/source/revision/{$project->id}/{$xfullpath}/{$h['rev']}",
$this->lang->line('Details'));
print '</td>';
}
print '</td>';
print '</tr>';
@ -170,13 +157,35 @@ $this->load->view (
// let's track the copy path.
//
$paths = $h['paths'];
$colspan = ($file['type'] == 'file')? 5: 4;
foreach ($paths as $p)
{
/*
if (array_key_exists ('copyfrom', $p) &&
$p['path'] == $curfolder && $p['action'] == 'A')
$p['path'] == $curfullpath && $p['action'] == 'A')
{
$curfolder = $p['copyfrom'];
print "<tr class='title'><td colspan=5>{$curfolder}</td></tr>";
$curfullpath = $p['copyfrom'];
print "<tr class='title'><td colspan='{$colspan}'>{$curfullpath}</td></tr>";
}
*/
if (array_key_exists ('copyfrom', $p) &&
$p['action'] == 'A')
{
$d = $curfullpath;
$f = '';
while ($d != '/' && $d != '')
{
if ($d == $p['path'])
{
$curfullpath = $p['copyfrom'] . $f;
print "<tr class='title'><td colspan='{$colspan}'>{$curfullpath}</td></tr>";
break;
}
$d = dirname ($d);
$f = substr ($curfullpath, strlen($d));
}
}
}

View File

@ -37,46 +37,61 @@ $history = $file['history'];
<div class="title" id="project_source_revision_mainarea_title">
<?php
function print_path ($project, $path, $rev, $converter)
{
$exps = explode ('/', $path);
if ($revision <= 0)
{
$revreq = '';
$revreqroot = '';
}
else
{
$revreq = "/{$file['created_rev']}";
$revreqroot = '/' . $this->converter->AsciiToHex ('.') . $revreq;
}
print anchor (
"/source/revision/{$project->id}{$revreqroot}",
htmlspecialchars($project->name));
$exps = explode ('/', $headpath);
$expsize = count($exps);
$par = '';
for ($i = 1; $i < $expsize; $i++)
{
$par .= '/' . $exps[$i];
$hexpar = $converter->AsciiToHex ($par);
print '/';
$xpar = "source/revision/folder/{$project->id}/{$hexpar}";
if ($rev != '') $xpar .= "/{$rev}";
print anchor ($xpar, htmlspecialchars($exps[$i]));
}
}
$xpar = $this->converter->AsciiToHex ($par);
$hexfolder = $this->converter->AsciiToHex('.');
print anchor ("/source/revision/folder/{$project->id}/{$hexfolder}/{$revision}", htmlspecialchars($project->name));
if ($folder != '') print_path ($project, $folder, $revision, $this->converter);
print '/';
print anchor (
"source/revision/{$project->id}/{$xpar}{$revreq}",
htmlspecialchars($exps[$i]));
}
if ($headpath != $file['fullpath'])
{
print ' - ';
print htmlspecialchars($file['fullpath']);
}
?>
</div>
<div class="menu" id="project_source_revision_mainarea_menu">
<?php
$hexfolder = $this->converter->AsciiToHex(($folder == '')? '.': $folder);
if ($revision > 0 && $revision < $next_revision)
{
print anchor ("source/revision/{$type}/{$project->id}/{$hexfolder}", $this->lang->line('Head revision'));
print ' | ';
}
print anchor ("source/history/{$type}/{$project->id}/{$hexfolder}", $this->lang->line('History'));
$xpar = $this->converter->AsciiToHex(($headpath == '')? '.': $headpath);
if ($revision > 0 && $revision < $next_revision)
{
print anchor ("source/revision/{$project->id}/{$xpar}", $this->lang->line('Head revision'));
print ' | ';
}
print anchor ("source/history/{$project->id}/{$xpar}", $this->lang->line('History'));
?>
</div> <!-- project_source_revision_mainarea_menu -->
<div class="infostrip" id="project_source_revision_mainarea_infostrip">
<?=anchor ("source/revision/{$type}/{$project->id}/${hexfolder}/{$prev_revision}", '<<')?>
<?=$this->lang->line('Revision')?>: <?=$history['rev']?>
<?=anchor ("source/revision/{$type}/{$project->id}/${hexfolder}/{$next_revision}", '>>')?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($history['author'])?> |
<?=$this->lang->line('Last updated on')?>: <?=date('r', strtotime($history['date']))?>
<?=anchor ("source/revision/{$project->id}/${xpar}/{$prev_revision}", '<<')?>
<?=$this->lang->line('Revision')?>: <?=$history['rev']?>
<?=anchor ("source/revision/{$project->id}/${xpar}/{$next_revision}", '>>')?> |
<?=$this->lang->line('Author')?>: <?=htmlspecialchars($history['author'])?> |
<?=$this->lang->line('Last updated on')?>: <?=date('r', strtotime($history['date']))?>
</div>
@ -90,29 +105,33 @@ print anchor ("source/history/{$type}/{$project->id}/{$hexfolder}", $this->lang-
<div class="title">Files updated</div>
<table id="project_source_revision_mainarea_result_table">
<?php
/*
print '<tr class="heading">';
print '<th>' . $this->lang->line('Path') . '</th>';
print '<th></th>';
print '</tr>';
*/
$rowclasses = array ('even', 'odd');
$rowclasses = array ('odd', 'even');
$rowcount = 0;
foreach ($history['paths'] as $p)
{
$rowclass = $rowclasses[++$rowcount % 2];
print "<tr class='{$rowclass}'>";
$hexpar = $this->converter->AsciiToHex ($p['path']);
$xpar = $this->converter->AsciiToHex ($p['path']);
print "<td class='{$p['action']}'>";
print anchor ("source/file/{$project->id}/{$hexpar}/{$history['rev']}", htmlspecialchars($p['path']));
print anchor ("source/file/{$project->id}/{$xpar}/{$history['rev']}", htmlspecialchars($p['path']));
print '</td>';
/*
print '<td>';
print anchor ("source/blame/{$project->id}/{$hexpar}/{$history['rev']}", $this->lang->line('Blame'));
print anchor ("source/blame/{$project->id}/{$xpar}/{$history['rev']}", $this->lang->line('Blame'));
print ' ';
print anchor ("source/diff/{$project->id}/{$hexpar}/{$history['rev']}", $this->lang->line('Difference'));
print anchor ("source/diff/{$project->id}/{$xpar}/{$history['rev']}", $this->lang->line('Difference'));
print '</td>';
*/
print '</tr>';
}