* code for task #6708.
This commit is contained in:
@@ -45,6 +45,7 @@ $filter->mail = new stdclass();
|
||||
$filter->user = new stdclass();
|
||||
$filter->block = new stdclass();
|
||||
$filter->file = new stdclass();
|
||||
$filter->repo = new stdclass();
|
||||
|
||||
$filter->block->default = new stdclass();
|
||||
$filter->block->main = new stdclass();
|
||||
@@ -212,3 +213,16 @@ $filter->git->cat->get['repoUrl'] = 'reg::base64';
|
||||
$filter->git->diff->get['repoUrl'] = 'reg::base64';
|
||||
$filter->svn->cat->get['repoUrl'] = 'reg::base64';
|
||||
$filter->svn->diff->get['repoUrl'] = 'reg::base64';
|
||||
|
||||
$filter->repo->default = new stdclass();
|
||||
$filter->repo->diff = new stdclass();
|
||||
$filter->repo->view = new stdclass();
|
||||
|
||||
$filter->repo->default->get['path'] = 'reg::base64';
|
||||
$filter->repo->default->get['entry'] = 'reg::base64';
|
||||
|
||||
$filter->repo->default->cookie['repoBranch'] = 'reg::any';
|
||||
$filter->repo->diff->cookie['arrange'] = 'reg::word';
|
||||
$filter->repo->diff->cookie['repoPairs'] = 'array';
|
||||
$filter->repo->view->cookie['repoPairs'] = 'array';
|
||||
$filter->repo->ajaxsynccomment->cookie['syncBranch'] = 'reg::any';
|
||||
|
||||
+11
-6
@@ -163,12 +163,17 @@ define('TABLE_TESTSUITE', '`' . $config->db->prefix . 'testsuite`');
|
||||
define('TABLE_SUITECASE', '`' . $config->db->prefix . 'suitecase`');
|
||||
define('TABLE_TESTREPORT', '`' . $config->db->prefix . 'testreport`');
|
||||
|
||||
define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
|
||||
define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`');
|
||||
define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
|
||||
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');
|
||||
define('TABLE_NOTIFY', '`' . $config->db->prefix . 'notify`');
|
||||
define('TABLE_OAUTH', '`' . $config->db->prefix . 'oauth`');
|
||||
define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
|
||||
define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`');
|
||||
define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
|
||||
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');
|
||||
define('TABLE_NOTIFY', '`' . $config->db->prefix . 'notify`');
|
||||
define('TABLE_OAUTH', '`' . $config->db->prefix . 'oauth`');
|
||||
|
||||
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
|
||||
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
|
||||
define('TABLE_REPOFILES', '`' . $config->db->prefix . 'repofiles`');
|
||||
define('TABLE_REPOBRANCH', '`' . $config->db->prefix . 'repobranch`');
|
||||
if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`');
|
||||
|
||||
$config->objectTables['product'] = TABLE_PRODUCT;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
-- DROP TABLE IF EXISTS `zt_repo`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_repo` (
|
||||
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`path` varchar(255) NOT NULL,
|
||||
`prefix` varchar(100) NOT NULL,
|
||||
`encoding` varchar(20) NOT NULL,
|
||||
`SCM` varchar(10) NOT NULL,
|
||||
`client` varchar(100) NOT NULL,
|
||||
`commits` mediumint(8) unsigned NOT NULL,
|
||||
`account` varchar(30) NOT NULL,
|
||||
`password` varchar(30) NOT NULL,
|
||||
`encrypt` varchar(30) NOT NULL DEFAULT 'plain',
|
||||
`acl` text NOT NULL,
|
||||
`synced` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`lastSync` datetime NOT NULL,
|
||||
`deleted` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_repobranch`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_repobranch` (
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`revision` mediumint(8) unsigned NOT NULL,
|
||||
`branch` varchar(255) NOT NULL,
|
||||
UNIQUE KEY `repo_revision_branch` (`repo`,`revision`,`branch`),
|
||||
KEY `branch` (`branch`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_repohistory`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_repohistory` (
|
||||
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
`repo` mediumint(9) NOT NULL,
|
||||
`revision` varchar(40) NOT NULL,
|
||||
`commit` mediumint(8) unsigned NOT NULL,
|
||||
`comment` text NOT NULL,
|
||||
`committer` varchar(100) NOT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `repo` (`repo`),
|
||||
KEY `revision` (`revision`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_repofiles`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_repofiles` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`revision` mediumint(8) unsigned NOT NULL,
|
||||
`path` varchar(255) NOT NULL,
|
||||
`parent` varchar(255) NOT NULL,
|
||||
`type` varchar(20) NOT NULL,
|
||||
`action` char(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `path` (`path`),
|
||||
KEY `parent` (`parent`),
|
||||
KEY `repo` (`repo`),
|
||||
KEY `revision` (`revision`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `zt_bug` CHANGE `caseVersion` `caseVersion` smallint(6) NOT NULL AFTER `case`;
|
||||
ALTER TABLE `zt_bug` ADD `repo` mediumint(8) unsigned NOT NULL AFTER `result`;
|
||||
ALTER TABLE `zt_bug` ADD `lines` varchar(10) COLLATE 'utf8_general_ci' NOT NULL AFTER `repo`;
|
||||
ALTER TABLE `zt_bug` ADD `v1` varchar(40) COLLATE 'utf8_general_ci' NOT NULL AFTER `lines`;
|
||||
ALTER TABLE `zt_bug` ADD `v2` varchar(40) COLLATE 'utf8_general_ci' NOT NULL AFTER `v1`;
|
||||
ALTER TABLE `zt_bug` ADD `repoType` varchar(30) COLLATE 'utf8_general_ci' NOT NULL DEFAULT '' AFTER `v2`;
|
||||
ALTER TABLE `zt_bug` ADD `entry` varchar(255) COLLATE 'utf8_general_ci' NOT NULL AFTER `repo`;
|
||||
@@ -2273,7 +2273,7 @@ class baseRouter
|
||||
* 为了安全起见,对公网环境隐藏脚本路径。
|
||||
* If the ip is pulic, hidden the full path of scripts.
|
||||
*/
|
||||
$remoteIP = helper::getRemoteIp();
|
||||
$remoteIP = zget($_SERVER, "REMOTE_ADDR", '');
|
||||
if(!defined('IN_SHELL') and !($remoteIP == '127.0.0.1' or filter_var($remoteIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false))
|
||||
{
|
||||
$errorLog = str_replace($this->getBasePath(), '', $errorLog);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
$config = new stdclass();
|
||||
$config->debug = false;
|
||||
@@ -0,0 +1,455 @@
|
||||
<?php
|
||||
class Git
|
||||
{
|
||||
public $client;
|
||||
public $root;
|
||||
|
||||
public function __construct($client, $root, $username, $password, $encoding = 'UTF-8')
|
||||
{
|
||||
putenv('LC_CTYPE=en_US.UTF-8');
|
||||
|
||||
$this->client = $client;
|
||||
$this->root = rtrim($root, DIRECTORY_SEPARATOR);
|
||||
$this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : '';
|
||||
|
||||
chdir($this->root);
|
||||
exec("{$this->client} config core.quotepath false");
|
||||
}
|
||||
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
$sub = '';
|
||||
chdir($this->root);
|
||||
if(!empty($path)) $sub = ":$path";
|
||||
if(!empty($this->branch))$revision = $this->branch;
|
||||
$cmd = escapeCmd("$this->client ls-tree -l $revision$sub");
|
||||
$list = execCmd($cmd . ' 2>&1', 'array', $result);
|
||||
if($result) return array();
|
||||
|
||||
$infos = array();
|
||||
foreach($list as $entry)
|
||||
{
|
||||
list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry);
|
||||
|
||||
/* Get commit info. */
|
||||
$pathName = ltrim($path . DIRECTORY_SEPARATOR . $name, DIRECTORY_SEPARATOR);
|
||||
$cmd = escapeCmd("$this->client log -1 $this->branch -- $pathName");
|
||||
$commit = execCmd($cmd, 'array');
|
||||
$logs = $this->parseLog($commit);
|
||||
|
||||
if($size > 1024 * 1024)
|
||||
{
|
||||
$size = round($size / (1024 * 1024), 2) . 'MB';
|
||||
}
|
||||
else if($size > 1024)
|
||||
{
|
||||
$size = round($size / 1024, 2) . 'KB';
|
||||
}
|
||||
else
|
||||
{
|
||||
$size .= 'Bytes';
|
||||
}
|
||||
|
||||
$info = new stdClass();
|
||||
$info->name = $name;
|
||||
$info->kind = $kind == 'tree' ? 'dir' : 'file';
|
||||
$info->revision = $logs ? $logs[0]->revision : $revision;
|
||||
$info->size = $size;
|
||||
$info->account = $logs ? $logs[0]->committer : '';
|
||||
$info->date = $logs ? $logs[0]->time : '';
|
||||
$info->comment = $logs ? $logs[0]->comment : '';
|
||||
$infos[] = $info;
|
||||
unset($info);
|
||||
}
|
||||
|
||||
/* Sort by kind */
|
||||
foreach($infos as $key => $info) $kinds[$key] = $info->kind;
|
||||
if($infos) array_multisort($kinds, SORT_ASC, $infos);
|
||||
|
||||
return $infos;
|
||||
}
|
||||
|
||||
public function branch()
|
||||
{
|
||||
chdir($this->root);
|
||||
|
||||
/* Get local branch. */
|
||||
$cmd = escapeCmd("$this->client branch");
|
||||
$list = execCmd($cmd . ' 2>&1', 'array', $result);
|
||||
if($result) return array();
|
||||
|
||||
$branches = array();
|
||||
foreach($list as $localBranch)
|
||||
{
|
||||
if($localBranch{0} == '*') $localBranch = substr($localBranch, 1);
|
||||
|
||||
$localBranch = trim($localBranch);
|
||||
$branches[$localBranch] = $localBranch;
|
||||
}
|
||||
asort($branches);
|
||||
return $branches;
|
||||
}
|
||||
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
$revision = $this->branch ? $this->branch : 'HEAD';
|
||||
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client log -10 $revision -- $path"), 'array');
|
||||
$logs = $this->parseLog($list);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
$count = $count == 0 ? '' : "-n $count";
|
||||
/* compatible with svn. */
|
||||
if($fromRevision == 'HEAD' and $this->branch) $fromRevision = $this->branch;
|
||||
if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch;
|
||||
if($fromRevision === $toRevision)
|
||||
{
|
||||
$logs = array();
|
||||
chdir($this->root);
|
||||
|
||||
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status -1 $fromRevision -- $path"), 'array');
|
||||
$logs = $this->parseLog($list);
|
||||
return $logs;
|
||||
}
|
||||
|
||||
if(!$fromRevision)
|
||||
{
|
||||
$revisions = " $toRevision";
|
||||
}
|
||||
else
|
||||
{
|
||||
$revisions = "$fromRevision..$toRevision";
|
||||
}
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client log $count $revisions -- $path"), 'array');
|
||||
$logs = $this->parseLog($list);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client blame -l $revision -- $path"), 'array');
|
||||
|
||||
$blames = array();
|
||||
$revLine = 0;
|
||||
$revision = '';
|
||||
foreach($list as $line)
|
||||
{
|
||||
if(empty($line)) continue;
|
||||
if($line{0} == '^') $line = substr($line, 1);
|
||||
preg_match('/^([0-9a-f]{39,40})\s.*\((\S+)\s+([\d-]+)\s(.*)\s(\d+)\)(.*)$/U', $line, $matches);
|
||||
|
||||
if(isset($matches[1]) and $matches[1] != $revision)
|
||||
{
|
||||
$blame = array();
|
||||
$blame['revision'] = $matches[1];
|
||||
$blame['committer'] = $matches[2];
|
||||
$blame['time'] = $matches[3];
|
||||
$blame['line'] = $matches[5];
|
||||
$blame['lines'] = 1;
|
||||
$blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1);
|
||||
|
||||
$revision = $matches[1];
|
||||
$revLine = $matches[5];
|
||||
$blames[$revLine] = $blame;
|
||||
}
|
||||
elseif(isset($matches[5]))
|
||||
{
|
||||
$blame = array();
|
||||
$blame['line'] = $matches[5];
|
||||
$blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1);
|
||||
|
||||
$blames[$matches[5]] = $blame;
|
||||
$blames[$revLine]['lines'] ++;
|
||||
}
|
||||
}
|
||||
return $blames;
|
||||
}
|
||||
|
||||
public function diff($path, $fromRevision, $toRevision)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
chdir($this->root);
|
||||
if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch;
|
||||
if($fromRevision == '^') $fromRevision = $toRevision . '^';
|
||||
if(strpos($fromRevision, '^') !== false)
|
||||
{
|
||||
$list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array');
|
||||
if(isset($list[1])) $fromRevision = $list[1];
|
||||
}
|
||||
$lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array');
|
||||
return $lines;
|
||||
}
|
||||
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
chdir($this->root);
|
||||
if($revision == 'HEAD' and $this->branch) $revision = $this->branch;
|
||||
$cmd = escapeCmd("$this->client show $revision:$entry");
|
||||
$content = execCmd($cmd);
|
||||
if(is_array($content)) $content = implode("\n", $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function info($entry, $revision = 'HEAD')
|
||||
{
|
||||
chdir($this->root);
|
||||
if($revision == 'HEAD' and $this->branch) $revision = $this->branch;
|
||||
$path = ltrim($entry, DIRECTORY_SEPARATOR);
|
||||
$cmd = escapeCmd("$this->client ls-tree $revision -- $path");
|
||||
$result = execCmd($cmd);
|
||||
$kind = '';
|
||||
if($result)
|
||||
{
|
||||
$results = explode("\n", trim($result));
|
||||
if(count($results) >= 2)
|
||||
{
|
||||
$kind = 'dir';
|
||||
}
|
||||
else
|
||||
{
|
||||
list($mode, $type) = explode(' ', $results[0]);
|
||||
$kind = $type == 'tree' ? 'dir' : 'file';
|
||||
}
|
||||
}
|
||||
|
||||
$list = execCmd(escapeCmd("$this->client log -1 $revision --pretty=format:%H -- $path"), 'array');
|
||||
$revision = $list[0];
|
||||
$info = new stdclass();
|
||||
$info->kind = $kind;
|
||||
$info->path = $entry;
|
||||
$info->revision = $revision;
|
||||
$info->root = $this->root;
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function parseDiff($lines)
|
||||
{
|
||||
if(empty($lines)) return array();
|
||||
$diffs = array();
|
||||
$num = count($lines);
|
||||
$endLine = end($lines);
|
||||
if(strpos($endLine, '\ No newline at end of file') === 0) $num -= 1;
|
||||
|
||||
$newFile = false;
|
||||
for($i = 0; $i < $num; $i ++)
|
||||
{
|
||||
$diffFile = new stdclass();
|
||||
if(strpos($lines[$i], "diff --git ") === 0)
|
||||
{
|
||||
$fileInfo = explode(' ',$lines[$i]);
|
||||
$fileName = substr($fileInfo[2], strpos($fileInfo[2], '/') + 1);
|
||||
$diffFile->fileName = $fileName;
|
||||
for($i++; $i < $num; $i ++)
|
||||
{
|
||||
$diff = new stdclass();
|
||||
/* Fix bug #1757. */
|
||||
if($lines[$i] == '+++ /dev/null') $newFile = true;
|
||||
if(strpos($lines[$i], '+++', 0) !== false) continue;
|
||||
if(strpos($lines[$i], '---', 0) !== false) continue;
|
||||
if(strpos($lines[$i], '======', 0) !== false) continue;
|
||||
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i]))
|
||||
{
|
||||
$startLines = trim(str_replace(array('@', '+', '-'), '', $lines[$i]));
|
||||
list($oldStartLine, $newStartLine) = explode(' ', $startLines);
|
||||
list($diff->oldStartLine) = explode(',', $oldStartLine);
|
||||
list($diff->newStartLine) = explode(',', $newStartLine);
|
||||
$oldCurrentLine = $diff->oldStartLine;
|
||||
$newCurrentLine = $diff->newStartLine;
|
||||
if($newFile)
|
||||
{
|
||||
$oldCurrentLine = $diff->newStartLine;
|
||||
$newCurrentLine = $diff->oldStartLine;
|
||||
}
|
||||
$newLines = array();
|
||||
for($i++; $i < $num; $i ++)
|
||||
{
|
||||
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i]))
|
||||
{
|
||||
$i --;
|
||||
break;
|
||||
}
|
||||
if(strpos($lines[$i], "diff --git ") === 0) break;
|
||||
|
||||
$line = $lines[$i];
|
||||
if(strpos($line, '\ No newline at end of file') === 0)continue;
|
||||
$sign = empty($line) ? '' : $line{0};
|
||||
if($sign == '-' and $newFile) $sign = '+';
|
||||
$type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old';
|
||||
if($sign == '-' || $sign == '+')
|
||||
{
|
||||
$line = substr_replace($line, ' ', 1, 0);
|
||||
if($newFile) $line = preg_replace('/^\-/', '+', $line);
|
||||
}
|
||||
|
||||
$newLine = new stdclass();
|
||||
$newLine->type = $type;
|
||||
$newLine->oldlc = $type != 'new' ? $oldCurrentLine : '';
|
||||
$newLine->newlc = $type != 'old' ? $newCurrentLine : '';
|
||||
$newLine->line = htmlspecialchars($line);
|
||||
|
||||
if($type != 'new') $oldCurrentLine++;
|
||||
if($type != 'old') $newCurrentLine++;
|
||||
|
||||
$newLines[] = $newLine;
|
||||
}
|
||||
|
||||
$diff->lines = $newLines;
|
||||
$diffFile->contents[] = $diff;
|
||||
}
|
||||
|
||||
if(isset($lines[$i]) and strpos($lines[$i], "diff --git ") === 0)
|
||||
{
|
||||
$i --;
|
||||
$newFile = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$diffs[] = $diffFile;
|
||||
}
|
||||
}
|
||||
return $diffs;
|
||||
}
|
||||
|
||||
public function getCommitCount($commits = 0, $lastVersion = '')
|
||||
{
|
||||
chdir($this->root);
|
||||
$revision = $this->branch ? $this->branch : 'HEAD';
|
||||
return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string');
|
||||
}
|
||||
|
||||
public function getFirstRevision()
|
||||
{
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client rev-list --reverse HEAD -- ./"), 'array');
|
||||
return $list[0];
|
||||
}
|
||||
|
||||
public function getLatestRevision()
|
||||
{
|
||||
chdir($this->root);
|
||||
$revision = $this->branch ? $this->branch : 'HEAD';
|
||||
$list = execCmd(escapeCmd("$this->client rev-list -1 $revision -- ./"), 'array');
|
||||
return $list[0];
|
||||
}
|
||||
|
||||
public function getCommits($version = '', $count = 0, $branch = '')
|
||||
{
|
||||
if($version == 'HEAD' and $branch) $version = $branch;
|
||||
$revision = empty($version) ? $revision : $version;
|
||||
$revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision;
|
||||
$count = $count == 0 ? '' : "-n $count";
|
||||
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array');
|
||||
$commits = $this->parseLog($list);
|
||||
|
||||
$logs = array();
|
||||
foreach($commits as $commit)
|
||||
{
|
||||
$hash = $commit->revision;
|
||||
$log = new stdClass();
|
||||
$log->committer = $commit->committer;
|
||||
$log->revision = $commit->revision;
|
||||
$log->comment = $commit->comment;
|
||||
$log->time = $commit->time;
|
||||
$logs['commits'][$hash] = $log;
|
||||
$logs['files'][$hash] = array();
|
||||
}
|
||||
if(empty($logs)) return $logs;
|
||||
|
||||
$hash = '';
|
||||
$files = execCmd(escapeCmd("$this->client whatchanged $count $revision --pretty=format:%an@_@%cd@_@%H@_@%s -- ./"), 'array');
|
||||
foreach($files as $commit)
|
||||
{
|
||||
$commit = trim($commit);
|
||||
if(empty($commit)) continue;
|
||||
$parsedCommit = explode('@_@', $commit);
|
||||
if(count($parsedCommit) == 4)
|
||||
{
|
||||
list($account, $date, $hash, $comment) = $parsedCommit;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = explode(' ', $commit);
|
||||
$file = end($file);
|
||||
list($action, $path) = explode("\t", $file);
|
||||
$parsedFile = new stdclass();
|
||||
$parsedFile->revision = $hash;
|
||||
$parsedFile->path = '/' . trim($path);
|
||||
$parsedFile->type = 'file';
|
||||
$parsedFile->action = $action;
|
||||
$logs['files'][$hash][] = $parsedFile;
|
||||
}
|
||||
}
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function parseLog($logs)
|
||||
{
|
||||
$parsedLogs = array();
|
||||
$i = 0;
|
||||
foreach($logs as $line)
|
||||
{
|
||||
if(strpos($line, 'commit ') === 0)
|
||||
{
|
||||
if(isset($log))
|
||||
{
|
||||
$log->comment = trim($comment);
|
||||
$log->change = $changes;
|
||||
$parsedLogs[$i] = $log;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$log = new stdclass();
|
||||
$comment = '';
|
||||
$changes = array();
|
||||
|
||||
$log->revision = trim(preg_replace('/^commit/', '', $line));
|
||||
}
|
||||
elseif(strpos($line, 'Author:') === 0)
|
||||
{
|
||||
$account = preg_replace('/^Author:/', '', $line);
|
||||
$log->committer = trim(preg_replace('/<[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+>/', '', $account));
|
||||
}
|
||||
elseif(strpos($line, 'Date:') === 0)
|
||||
{
|
||||
$date = trim(preg_replace('/^Date:/', '', $line));
|
||||
$log->time = date('Y-m-d H:i:s', strtotime($date));
|
||||
}
|
||||
elseif(preg_match('/^\s{2,}/', $line))
|
||||
{
|
||||
$comment .= $line;
|
||||
}
|
||||
elseif(strpos($line, "\t") !== false)
|
||||
{
|
||||
list($action, $entry) = explode("\t", $line);
|
||||
$entry = '/' . trim($entry);
|
||||
$pathInfo = array();
|
||||
$pathInfo['action'] = $action;
|
||||
$pathInfo['kind'] = 'file';
|
||||
$changes[$entry] = $pathInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($log))
|
||||
{
|
||||
$log->comment = trim($comment);
|
||||
$log->change = $changes;
|
||||
$parsedLogs[$i] = $log;
|
||||
}
|
||||
|
||||
return $parsedLogs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
class scm
|
||||
{
|
||||
public $engine;
|
||||
|
||||
public function setEngine($repo)
|
||||
{
|
||||
$className = $repo->SCM;
|
||||
if(!class_exists($className)) require(strtolower($className) . '.class.php');
|
||||
$this->engine = new $className($repo->client, $repo->path, $repo->account, $repo->password, $repo->encoding);
|
||||
}
|
||||
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->ls($path, $revision);
|
||||
}
|
||||
|
||||
public function branch()
|
||||
{
|
||||
return $this->engine->branch();
|
||||
}
|
||||
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
|
||||
{
|
||||
return $this->engine->log($path, $fromRevision, $toRevision);
|
||||
}
|
||||
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
return $this->engine->blame($path, $revision);
|
||||
}
|
||||
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
return $this->engine->getLastLog($path, $count);
|
||||
}
|
||||
|
||||
public function diff($path, $fromRevision = 0, $toRevision = 'HEAD', $parse = 'yes')
|
||||
{
|
||||
$diffs = $this->engine->diff($path, $fromRevision, $toRevision);
|
||||
|
||||
if($parse != 'yes') return implode("\n", $diffs);
|
||||
return $this->engine->parseDiff($diffs);
|
||||
}
|
||||
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->cat($entry, $revision);
|
||||
}
|
||||
|
||||
public function info($entry, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->info($entry, $revision);
|
||||
}
|
||||
|
||||
public function getCommitCount($commits = 0, $lastVersion = 0)
|
||||
{
|
||||
return $this->engine->getCommitCount($commits, $lastVersion);
|
||||
}
|
||||
|
||||
public function getLatestRevision()
|
||||
{
|
||||
return $this->engine->getLatestRevision();
|
||||
}
|
||||
|
||||
public function getFirstRevision()
|
||||
{
|
||||
return $this->engine->getFirstRevision();
|
||||
}
|
||||
|
||||
public function getCommits($version = '', $count = 0, $branch = '')
|
||||
{
|
||||
return $this->engine->getCommits($version, $count, $branch);
|
||||
}
|
||||
}
|
||||
|
||||
function escapeCmd($cmd)
|
||||
{
|
||||
$codes = array('#', '&', ';', '`', '|', '*', '?', '~', '<', '>', '^', '[', ']', '{', '}', '$', ',', '\x0A', '\xFF');
|
||||
if(DIRECTORY_SEPARATOR == '/') $codes[] = '\\';
|
||||
foreach($codes as $code) $cmd = str_replace($code, '\\' . $code, $cmd);
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
function execCmd($cmd, $return = 'string', &$result = 0, $type = 'utf-8')
|
||||
{
|
||||
if(file_exists(dirname(__FILE__) . '/config.php')) include dirname(__FILE__) . '/config.php';
|
||||
if($type != 'utf-8') $cmd = iconv('utf-8', $type . '//TRANSLIT', $cmd);
|
||||
|
||||
$debug = (isset($config->debug) and $config->debug);
|
||||
if($debug and strpos($cmd, '2>&1') === false) $cmd = $cmd . ' 2>&1';
|
||||
|
||||
ob_start();
|
||||
passthru($cmd, $result);
|
||||
$output = ob_get_clean();
|
||||
if($debug and $result)
|
||||
{
|
||||
a('The command is ' . $cmd);
|
||||
a('The result is ' . $result);
|
||||
a($output);
|
||||
}
|
||||
|
||||
/* When output is empty and with chinese then try execute again in windows. */
|
||||
if(strtolower(substr(PHP_OS, 0, 3)) == 'win' and empty($output) and $type == 'utf-8' and preg_match("/[\x7f-\xff]/", $cmd)) $output = execCmd($cmd, 'string', $result, 'gbk');
|
||||
if($return == 'array') return explode("\n", trim($output));
|
||||
return $output;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
include 'scm.class.php';
|
||||
|
||||
function subversionTest()
|
||||
{
|
||||
$repo->SCM = 'Subversion';
|
||||
$repo->client = '/usr/bin/svn';
|
||||
$repo->account = 'aaa';
|
||||
$repo->password = 'aaaaaa';
|
||||
|
||||
$scm = new scm($repo);
|
||||
print_r($scm->cat("http://svn.aaa.5upm.cn/bb/aaa"));
|
||||
}
|
||||
|
||||
subversionTest();
|
||||
@@ -0,0 +1,464 @@
|
||||
<?php
|
||||
class Subversion
|
||||
{
|
||||
public $client;
|
||||
public $root;
|
||||
public $account;
|
||||
public $password;
|
||||
public $ssh;
|
||||
public $remote;
|
||||
public $encoding;
|
||||
|
||||
public function __construct($client, $root, $account, $password, $encoding = 'UTF-8')
|
||||
{
|
||||
putenv('LC_CTYPE=en_US.UTF-8');
|
||||
$this->root = rtrim($root, DIRECTORY_SEPARATOR);
|
||||
$this->account = $account;
|
||||
$this->password = $password;
|
||||
$this->encoding = $encoding;
|
||||
$this->ssh = (stripos($this->root, 'svn') === 0 or stripos($this->root, 'https') === 0) ? true : false;
|
||||
$this->remote = !(stripos($this->root, 'file') === 0);
|
||||
$this->client = $this->remote ? $client . " --username @account@ --password @password@" : $client;
|
||||
if($this->encoding == 'utf-8') $this->encoding = 'gbk';
|
||||
}
|
||||
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
$resourcePath = $path;
|
||||
$path = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($path)) . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'ls', "-r $revision --xml")));
|
||||
$list = execCmd($cmd, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$path = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'ls', "-r $revision --xml")));
|
||||
$list = execCmd($cmd, 'string', $result);
|
||||
if($result) $list = '';
|
||||
}
|
||||
$listObject = simplexml_load_string($list);
|
||||
if(!empty($list) and empty($listObject))
|
||||
{
|
||||
$list = helper::convertEncoding($list, $this->encoding, 'utf-8');
|
||||
$listObject = simplexml_load_string($list);
|
||||
}
|
||||
if(!empty($listObject->list->entry)) $listObject = $listObject->list->entry;
|
||||
$infos = array();
|
||||
if(empty($listObject)) return $infos;
|
||||
|
||||
foreach($listObject as $list)
|
||||
{
|
||||
$info = new stdclass();
|
||||
$info->name = (string)$list->name;
|
||||
$info->kind = (string)$list['kind'];
|
||||
$info->revision = (int)$list->commit['revision'];
|
||||
$info->account = (string)$list->commit->author;
|
||||
$info->date = date('Y-m-d H:i:s', strtotime($list->commit->date));
|
||||
$info->size = $info->kind == 'file' ? (int)$list->size > 1024 ? round((int)$list->size / 1024, 2) . "KB" : (int)$list->size . 'Bytes' : 0;
|
||||
$info->comment = '';
|
||||
$infos[] = $info;
|
||||
}
|
||||
|
||||
/* Sort by kind */
|
||||
foreach($infos as $key => $info) $kind[$key] = $info->kind;
|
||||
if($infos) array_multisort($kind, SORT_ASC, $infos);
|
||||
|
||||
return $infos;
|
||||
}
|
||||
|
||||
public function branch()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
$path = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($path)) . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'log', "--limit $count --xml")));
|
||||
$comments = execCmd($cmd, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$path = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'log', "--limit $count --xml")));
|
||||
$comments = execCmd($cmd, 'string', $result);
|
||||
if($result) $comments = '';
|
||||
}
|
||||
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
if(!empty($comments) and empty($parsedComments))
|
||||
{
|
||||
$comments = helper::convertEncoding($comments, $this->encoding, 'utf-8');
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
}
|
||||
$logs = array();
|
||||
foreach($parsedComments->logentry as $entry)
|
||||
{
|
||||
$log = new stdclass();
|
||||
$log->committer = (string)$entry->author;
|
||||
$log->revision = (int)$entry['revision'];
|
||||
$log->comment = trim((string)$entry->msg);
|
||||
$log->time = date('Y-m-d H:i:s', strtotime($entry->date));
|
||||
$log->change = array();
|
||||
$logs[] = $log;
|
||||
unset($log);
|
||||
}
|
||||
|
||||
/* Sort by kind */
|
||||
foreach($logs as $key => $log) $revision[$key] = $log->revision;
|
||||
if($logs) array_multisort($revision, SORT_DESC, $logs);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0, $quiet = false)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
$count = $count == 0 ? '' : "--limit $count";
|
||||
$param = $quiet ? '-q' : '-v';
|
||||
$path = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($path)) . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'log', "$count $param -r $fromRevision:$toRevision --xml")));
|
||||
$comments = execCmd($cmd, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$path = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'log', "$count $param -r $fromRevision:$toRevision --xml")));
|
||||
$comments = execCmd($cmd, 'string', $result);
|
||||
if($result) $comments = '';
|
||||
}
|
||||
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
if(!empty($comments) and empty($parsedComments))
|
||||
{
|
||||
$comments = helper::convertEncoding($comments, $this->encoding, 'utf-8');
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
}
|
||||
$logs = array();
|
||||
$revision = array();
|
||||
if(empty($parsedComments->logentry)) return $logs;
|
||||
|
||||
foreach($parsedComments->logentry as $entry)
|
||||
{
|
||||
$log = new stdclass();
|
||||
$log->committer = (string)$entry->author;
|
||||
$log->revision = (int)$entry['revision'];
|
||||
$log->comment = trim((string)$entry->msg);
|
||||
$log->time = date('Y-m-d H:i:s', strtotime($entry->date));
|
||||
$log->change = array();
|
||||
if(!empty($entry->paths))
|
||||
{
|
||||
foreach($entry->paths->path as $path)
|
||||
{
|
||||
$pathInfo = array();
|
||||
foreach($path->attributes() as $attr => $value) $pathInfo[$attr] = (string)$value;
|
||||
$log->change[(string)$path] = $pathInfo;
|
||||
}
|
||||
}
|
||||
if(in_array($log->revision, $revision)) continue;
|
||||
|
||||
$logs[] = $log;
|
||||
$revision[] = $log->revision;
|
||||
unset($log);
|
||||
}
|
||||
|
||||
/* Sort by kind */
|
||||
if($logs) array_multisort($revision, SORT_DESC, $logs);
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
$path = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($path)) . '"';
|
||||
$file = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'cat', "-r $revision")));
|
||||
$blame = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'blame', "-r $revision --xml")));
|
||||
$output = execCmd($blame, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$path = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$file = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'cat', "-r $revision")));
|
||||
$blame = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'blame', "-r $revision --xml")));
|
||||
$output = execCmd($blame, 'string', $result);
|
||||
|
||||
if($result) return array();
|
||||
}
|
||||
|
||||
$content = execCmd($file, 'array');
|
||||
|
||||
$parsedResult = simplexml_load_string($output);
|
||||
if(!empty($output) and empty($parsedResult))
|
||||
{
|
||||
$output = helper::convertEncoding($output, $this->encoding, 'utf-8');
|
||||
$parsedResult = simplexml_load_string($output);
|
||||
}
|
||||
|
||||
$blames = array();
|
||||
$revLine = 0;
|
||||
$revision = '';
|
||||
if($parsedResult->target->entry)
|
||||
{
|
||||
foreach($parsedResult->target->entry as $line)
|
||||
{
|
||||
if($line->commit['revision'] != $revision)
|
||||
{
|
||||
$blame = array();
|
||||
$blame['revision'] = (int)$line->commit['revision'];
|
||||
$blame['committer'] = (string)$line->commit->author;
|
||||
$blame['time'] = substr($line->commit->date, 0, 10);
|
||||
$blame['line'] = (int)$line['line-number'];
|
||||
$blame['lines'] = 1;
|
||||
$blame['content'] = $content[$blame['line'] - 1];
|
||||
$revision = $blame['revision'];
|
||||
$revLine = $blame['line'];
|
||||
$blames[$revLine] = $blame;
|
||||
}
|
||||
else
|
||||
{
|
||||
$blame = array();
|
||||
$blame['line'] = (int)$line['line-number'];
|
||||
$blame['content'] = $content[$blame['line'] - 1];
|
||||
|
||||
$blames[$blame['line']] = $blame;
|
||||
$blames[$revLine]['lines'] ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $blames;
|
||||
}
|
||||
|
||||
public function diff($path, $fromRevision, $toRevision)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
if($fromRevision == '^') $fromRevision = $toRevision - 1;
|
||||
$path = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($path)) . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'diff', "-r $fromRevision:$toRevision")));
|
||||
$lines = execCmd($cmd, 'array', $result);
|
||||
if($result)
|
||||
{
|
||||
$path = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($path, 'diff', "-r $fromRevision:$toRevision")));
|
||||
$lines = execCmd($cmd, 'array', $result);
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
$resourcePath = $entry;
|
||||
$entry = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($entry)) . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($entry, 'cat', "-r $revision")));
|
||||
$content = execCmd($cmd, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$entry = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$cmd = $this->replaceAuth(escapeCmd($this->buildCMD($entry, 'cat', "-r $revision")));
|
||||
$content = execCmd($cmd, 'string', $result);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function info($entry, $revision = 'HEAD')
|
||||
{
|
||||
$resourcePath = $entry;
|
||||
$entry = '"' . $this->root . '/' . str_replace('%2F', '/', urlencode($entry)) . '"';
|
||||
$svnInfo = $this->replaceAuth(escapeCmd($this->buildCMD($entry, 'info', "-r $revision --xml")));
|
||||
$svninfo = execCmd($svnInfo, 'string', $result);
|
||||
if($result)
|
||||
{
|
||||
$entry = '"' . $this->root . '/' . $resourcePath . '"';
|
||||
$svnInfo = $this->replaceAuth(escapeCmd($this->buildCMD($entry, 'info', "-r $revision --xml")));
|
||||
$svninfo = execCmd($svnInfo, 'string', $result);
|
||||
if($result) $svninfo = '';
|
||||
}
|
||||
|
||||
$parsedSvnInfo = simplexml_load_string($svninfo);
|
||||
if(!empty($svninfo) and empty($parsedSvnInfo))
|
||||
{
|
||||
$svninfo = helper::convertEncoding($svninfo, $this->encoding, 'utf-8');
|
||||
$parsedSvnInfo = simplexml_load_string($svninfo);
|
||||
}
|
||||
$info = new stdclass();
|
||||
$info->kind = empty($parsedSvnInfo->entry['kind']) ? '' : (string)$parsedSvnInfo->entry['kind'];
|
||||
$info->path = empty($parsedSvnInfo->entry['path']) ? '' : (string)$parsedSvnInfo->entry['path'];
|
||||
$info->revision = empty($parsedSvnInfo->entry['revision']) ? '' : (int)$parsedSvnInfo->entry['revision'];
|
||||
$info->cRevision = empty($parsedSvnInfo->entry->commit['revision']) ? '' : (int)$parsedSvnInfo->entry->commit['revision'];
|
||||
$info->root = empty($parsedSvnInfo->entry->repository->root) ? '' : (string)$parsedSvnInfo->entry->repository->root;
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function parseDiff($lines)
|
||||
{
|
||||
if(empty($lines)) return array();
|
||||
$diffs = array();
|
||||
$num = count($lines);
|
||||
$endLine = end($lines);
|
||||
if(strpos($endLine, '\ No newline at end of file') === 0) $num -= 1;
|
||||
|
||||
for($i = 0; $i < $num; $i ++)
|
||||
{
|
||||
$diffFile = new stdclass();
|
||||
if(strpos($lines[$i], "Index: ") === 0)
|
||||
{
|
||||
$fileName = str_replace('Index: ', '', $lines[$i]);
|
||||
$diffFile->fileName = $fileName;
|
||||
for($i++; $i < $num; $i ++)
|
||||
{
|
||||
$diff = new stdclass();
|
||||
if(strpos($lines[$i], '+++', 0) !== false) continue;
|
||||
if(strpos($lines[$i], '---', 0) !== false) continue;
|
||||
if(strpos($lines[$i], '======', 0) !== false) continue;
|
||||
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@\\s*($)/A', $lines[$i]))
|
||||
{
|
||||
$startLines = trim(str_replace(array('@', '+', '-'), '', $lines[$i]));
|
||||
list($oldStartLine, $newStartLine) = explode(' ', $startLines);
|
||||
list($diff->oldStartLine) = explode(',', $oldStartLine);
|
||||
list($diff->newStartLine) = explode(',', $newStartLine);
|
||||
$oldCurrentLine = $diff->oldStartLine;
|
||||
$newCurrentLine = $diff->newStartLine;
|
||||
$newLines = array();
|
||||
for($i++; $i < $num; $i ++)
|
||||
{
|
||||
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@\\s*($)/A', $lines[$i]))
|
||||
{
|
||||
$i --;
|
||||
break;
|
||||
}
|
||||
if(strpos($lines[$i], "Index: ") === 0) break;
|
||||
|
||||
$line = $lines[$i];
|
||||
if(strpos($line, '\ No newline at end of file') === 0)continue;
|
||||
$sign = empty($line) ? '' : $line{0};
|
||||
$type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old';
|
||||
if($sign == '-' || $sign == '+') $line = substr_replace($line, ' ', 1, 0);
|
||||
|
||||
$newLine = new stdclass();
|
||||
$newLine->type = $type;
|
||||
$newLine->oldlc = $type != 'new' ? $oldCurrentLine : '';
|
||||
$newLine->newlc = $type != 'old' ? $newCurrentLine : '';
|
||||
$newLine->line = $line;
|
||||
|
||||
if($type != 'new') $oldCurrentLine++;
|
||||
if($type != 'old') $newCurrentLine++;
|
||||
|
||||
$newLines[] = $newLine;
|
||||
}
|
||||
|
||||
$diff->lines = $newLines;
|
||||
$diffFile->contents[] = $diff;
|
||||
}
|
||||
|
||||
if(isset($lines[$i]) and strpos($lines[$i], "Index: ") === 0)
|
||||
{
|
||||
$i --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$diffs[] = $diffFile;
|
||||
}
|
||||
}
|
||||
return $diffs;
|
||||
}
|
||||
|
||||
public function getCommitCount($commits = 0, $lastVersion = 0)
|
||||
{
|
||||
if(empty($commits)) $commits = 0;
|
||||
if(empty($lastVersion)) $lastVersion = 0;
|
||||
$lastRevision = $this->getLatestRevision();
|
||||
|
||||
$count = 10000;
|
||||
$from = $lastVersion;
|
||||
while(true)
|
||||
{
|
||||
$logs = $this->log('', $from, $lastRevision, empty($from) ? $count : $count + 1, $quiet = true);
|
||||
if(empty($logs)) break;
|
||||
|
||||
$num = empty($from) ? count($logs) : count($logs) - 1;
|
||||
$commits += $num;
|
||||
|
||||
$from = reset($logs);
|
||||
$from = $from->revision;
|
||||
if($from == $lastRevision) break;
|
||||
}
|
||||
return $commits;
|
||||
}
|
||||
|
||||
public function getFirstRevision()
|
||||
{
|
||||
$logs = $this->log('', 0, 'HEAD', 1, $quiet = true);
|
||||
if(empty($logs)) return 0;
|
||||
$firstLog = end($logs);
|
||||
return $firstLog->revision;
|
||||
}
|
||||
|
||||
public function getLatestRevision()
|
||||
{
|
||||
$info = $this->info('');
|
||||
return $info->cRevision;
|
||||
}
|
||||
|
||||
public function getCommits($version = '', $count = 0)
|
||||
{
|
||||
$count = $count == 0 ? '' : "--limit $count";
|
||||
$path = '"' . $this->root . '"';
|
||||
if(stripos($this->root, 'https') === 0 or stripos($this->root, 'svn') === 0)
|
||||
{
|
||||
$comments = str_replace("\\", "/", "$this->client log $count -v -r $version:0 --non-interactive --trust-server-cert-failures=cn-mismatch --trust-server-cert --no-auth-cache --xml $path");
|
||||
}
|
||||
else
|
||||
{
|
||||
$comments = str_replace("\\", "/", "$this->client log $count -v -r $version:0 --no-auth-cache --xml $path");
|
||||
}
|
||||
$comments = $this->replaceAuth(escapeCmd($comments));
|
||||
$comments = execCmd($comments, 'string', $result);
|
||||
if($result) $comments = '';
|
||||
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
if(!empty($comments) and empty($parsedComments))
|
||||
{
|
||||
$comments = helper::convertEncoding($comments, $this->encoding, 'utf-8');
|
||||
$parsedComments = simplexml_load_string($comments);
|
||||
}
|
||||
$logs = array();
|
||||
foreach($parsedComments->logentry as $entry)
|
||||
{
|
||||
$parsedLog = new stdClass();
|
||||
$parsedLog->committer = (string)$entry->author;
|
||||
$parsedLog->revision = (int)$entry['revision'];
|
||||
$parsedLog->comment = trim((string)$entry->msg);
|
||||
$parsedLog->time = date('Y-m-d H:i:s', strtotime($entry->date));
|
||||
$logs['commits'][$parsedLog->revision] = $parsedLog;
|
||||
$logs['files'][$parsedLog->revision] = array();
|
||||
if(!empty($entry->paths))
|
||||
{
|
||||
foreach($entry->paths->path as $file)
|
||||
{
|
||||
$parsedFile = new stdclass();
|
||||
$parsedFile->revision = $parsedLog->revision;
|
||||
$parsedFile->path = (string)$file;
|
||||
$parsedFile->type = (string)$file['kind'];
|
||||
$parsedFile->action = (string)$file['action'];
|
||||
$logs['files'][$parsedLog->revision][] = $parsedFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public function replaceAuth($cmd)
|
||||
{
|
||||
return str_replace(array('@account@', '@password@'), array($this->account, $this->password), $cmd);
|
||||
}
|
||||
|
||||
public function buildCMD($path, $action, $param)
|
||||
{
|
||||
if($this->ssh)
|
||||
{
|
||||
$cmd = str_replace("\\", "/", "$this->client $action $param --non-interactive --trust-server-cert-failures=cn-mismatch --trust-server-cert --no-auth-cache $path");
|
||||
}
|
||||
else
|
||||
{
|
||||
$cmd = str_replace("\\", "/", "$this->client $action $param --no-auth-cache $path");
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class adminModel extends model
|
||||
/* Check weak password when login. */
|
||||
if($this->app->moduleName == 'user' and $this->app->methodName == 'login')
|
||||
{
|
||||
if(!isset($_POST['passwordStrength']) return true;
|
||||
if(!isset($_POST['passwordStrength'])) return true;
|
||||
if(isset($this->config->safe->mode) and $this->post->passwordStrength < $this->config->safe->mode) return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ $lang->menuOrder[5] = 'my';
|
||||
$lang->menuOrder[10] = 'product';
|
||||
$lang->menuOrder[15] = 'project';
|
||||
$lang->menuOrder[20] = 'qa';
|
||||
$lang->menuOrder[25] = 'doc';
|
||||
$lang->menuOrder[30] = 'report';
|
||||
$lang->menuOrder[35] = 'company';
|
||||
$lang->menuOrder[40] = 'admin';
|
||||
$lang->menuOrder[25] = 'repo';
|
||||
$lang->menuOrder[30] = 'doc';
|
||||
$lang->menuOrder[35] = 'report';
|
||||
$lang->menuOrder[40] = 'company';
|
||||
$lang->menuOrder[45] = 'admin';
|
||||
|
||||
/* index menu order. */
|
||||
$lang->index->menuOrder[5] = 'product';
|
||||
@@ -76,6 +77,10 @@ $lang->testsuite->menuOrder = $lang->testcase->menuOrder;
|
||||
$lang->caselib->menuOrder = $lang->testcase->menuOrder;
|
||||
$lang->testreport->menuOrder = $lang->testcase->menuOrder;
|
||||
|
||||
$lang->repo->menuOrder[5] = 'log';
|
||||
$lang->repo->menuOrder[15] = 'settings';
|
||||
$lang->repo->menuOrder[20] = 'delete';
|
||||
|
||||
/* doc menu order. */
|
||||
$lang->doc->menuOrder[5] = 'list';
|
||||
$lang->doc->menuOrder[10] = 'product';
|
||||
|
||||
@@ -123,6 +123,7 @@ $lang->menu->my = '<span> 我的地盘</span>|my|index';
|
||||
$lang->menu->product = $lang->productCommon . '|product|index|locate=no';
|
||||
$lang->menu->project = $lang->projectCommon . '|project|index|locate=no';
|
||||
$lang->menu->qa = '测试|qa|index';
|
||||
$lang->menu->repo = '代码|repo|log';
|
||||
$lang->menu->doc = '文档|doc|index';
|
||||
$lang->menu->report = '统计|report|index';
|
||||
$lang->menu->company = '组织|company|index';
|
||||
@@ -331,6 +332,12 @@ $lang->caselib->menu->testsuite = array('link' => '套件|testsuite|browse|');
|
||||
$lang->caselib->menu->report = array('link' => '报告|testreport|browse|');
|
||||
$lang->caselib->menu->caselib = array('link' => '用例库|caselib|browse', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
|
||||
|
||||
$lang->repo = new stdclass();
|
||||
$lang->repo->menu = new stdclass();
|
||||
$lang->repo->menu->log = array('link' =>'浏览|repo|log|repoID=%s&entry=', 'alias' => 'diff,view,revision,showsynccomment');
|
||||
$lang->repo->menu->settings = '设置|repo|settings|repoID=%s';
|
||||
$lang->repo->menu->delete = array('link' => '删除|repo|delete|repoID=%s', 'target' => 'hiddenwin');
|
||||
|
||||
/* 文档视图菜单设置。*/
|
||||
$lang->doc = new stdclass();
|
||||
$lang->doc->menu = new stdclass();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
$config->program = new stdclass();
|
||||
$config->program->suffix['c'] = "cpp";
|
||||
$config->program->suffix['cpp'] = "cpp";
|
||||
$config->program->suffix['asp'] = "asp";
|
||||
$config->program->suffix['php'] = "php";
|
||||
$config->program->suffix['cs'] = "cs";
|
||||
$config->program->suffix['sh'] = "bash";
|
||||
$config->program->suffix['jsp'] = "java";
|
||||
$config->program->suffix['lua'] = "lua";
|
||||
$config->program->suffix['sql'] = "sql";
|
||||
$config->program->suffix['js'] = "javascript";
|
||||
$config->program->suffix['ini'] = "ini";
|
||||
$config->program->suffix['conf'] = "apache";
|
||||
$config->program->suffix['bat'] = "dos";
|
||||
$config->program->suffix['py'] = "python";
|
||||
$config->program->suffix['rb'] = "ruby";
|
||||
$config->program->suffix['as'] = "actionscript";
|
||||
$config->program->suffix['html'] = "xml";
|
||||
$config->program->suffix['xml'] = "xml";
|
||||
$config->program->suffix['htm'] = "xml";
|
||||
$config->program->suffix['pl'] = "perl";
|
||||
|
||||
$config->repo->cacheTime = 10;
|
||||
$config->repo->syncTime = 10;
|
||||
$config->repo->batchNum = 100;
|
||||
$config->repo->images = '|png|gif|jpg|ico|jpeg|bmp|';
|
||||
$config->repo->binary = '|pdf|';
|
||||
|
||||
$config->repo->editor = new stdclass();
|
||||
$config->repo->editor->view = array('id' => 'commentText', 'tools' => 'simpleTools');
|
||||
$config->repo->editor->diff = array('id' => 'commentText', 'tools' => 'simpleTools');
|
||||
@@ -0,0 +1,642 @@
|
||||
<?php
|
||||
/**
|
||||
* The control file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Yidong Wang, Jinyong Zhu
|
||||
* @package repo
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class repo extends control
|
||||
{
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$disFuncs = str_replace(' ', '', ini_get('disable_functions'));
|
||||
if(stripos(",$disFuncs,", ',exec,') !== false or stripos(",$disFuncs,", ',shell_exec,') !== false)
|
||||
{
|
||||
echo js::alert($this->lang->repo->error->useless);
|
||||
die(js::locate('back'));
|
||||
}
|
||||
|
||||
$this->scm = $this->app->loadClass('scm');
|
||||
$this->repos = $this->repo->getRepoPairs();
|
||||
if(common::hasPriv('repo', 'create')) $this->lang->modulePageActions = html::a(helper::createLink('repo', 'create'), "<i class='icon icon-plus text-muted'></i> " . $this->lang->repo->create, '', "class='btn'");
|
||||
if(empty($this->repos) and $this->methodName != 'create') die(js::locate($this->repo->createLink('create')));
|
||||
|
||||
/* Unlock session for wait to get data of repo. */
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create repo.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->repo->setMenu($this->repos);
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$repoID = $this->repo->create();
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
die(js::locate($this->repo->createLink('showSyncComment', "repoID=$repoID"), 'parent'));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->create;
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted');
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function settings($repoID = 0)
|
||||
{
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$needSync = $this->repo->saveSettings($repoID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
if(!$needSync)
|
||||
{
|
||||
die(js::locate($this->repo->createLink('showSyncComment', "repoID=$repoID"), 'parent'));
|
||||
}
|
||||
die(js::locate($this->repo->createLink('log', "repoID=$repoID"), 'parent'));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->settings;
|
||||
$this->view->repo = $this->repo->getRepoByID($repoID);
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted', !empty($repo->acl->users) ? $repo->acl->users : '');
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $confirm
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($repoID, $confirm = 'no')
|
||||
{
|
||||
if($confirm == 'no')
|
||||
{
|
||||
die(js::confirm($this->lang->repo->notice->delete, $this->repo->createLink('delete', "repoID=$repoID&confirm=yes")));
|
||||
}
|
||||
$this->dao->delete()->from(TABLE_REPO)->where('id')->eq($repoID)->exec();
|
||||
$this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->exec();
|
||||
$this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($repoID)->exec();
|
||||
$this->dao->delete()->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->exec();
|
||||
echo js::alert($this->lang->repo->notice->successDelete);
|
||||
die(js::locate($this->repo->createLink('log'), 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View repo file.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @param string $showBug
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view($repoID, $entry, $revision = 'HEAD', $showBug = 'false', $encoding = '')
|
||||
{
|
||||
if($this->get->entry) $entry = $this->get->entry;
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
$this->repo->setBackSession('view', $withOtherModule = true);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
|
||||
$file = $entry;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$entry = $this->repo->decodePath($entry);
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$info = $this->scm->info($entry, $revision);
|
||||
if($info->kind == 'dir') $this->locate($this->repo->createLink('log', "repoID=$repoID&entry=&revision=$revision", "entry=" . $this->repo->encodePath($info->path)));
|
||||
$content = $this->scm->cat($entry, $revision);
|
||||
$entry = urldecode($entry);
|
||||
$pathInfo = pathinfo($entry);
|
||||
$encoding = empty($encoding) ? $repo->encoding : $encoding;
|
||||
$encoding = strtolower(str_replace('_', '-', $encoding));
|
||||
|
||||
$suffix = '';
|
||||
if(isset($pathInfo["extension"])) $suffix = strtolower($pathInfo["extension"]);
|
||||
if(!$suffix or (!array_key_exists($suffix, $this->config->program->suffix) and strpos($this->config->repo->images, "|$suffix|") === false)) $suffix = $this->repo->isBinary($content, $suffix) ? 'binary' : 'c';
|
||||
|
||||
if(strpos($this->config->repo->images, "|$suffix|") !== false)
|
||||
{
|
||||
$content = base64_encode($content);
|
||||
}
|
||||
elseif($encoding != 'utf-8')
|
||||
{
|
||||
$content = helper::convertEncoding($content, $encoding);
|
||||
}
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager(0, 8, 1);
|
||||
|
||||
$commiters = $this->loadModel('user')->getCommiters();
|
||||
$logType = 'file';
|
||||
$revisions = $this->repo->getLogs($repo, '/' . $entry, 'HEAD', $logType, $pager);
|
||||
|
||||
$i = 0;
|
||||
foreach($revisions as $log)
|
||||
{
|
||||
if($revision == 'HEAD' and $i == 0) $revision = $log->revision;
|
||||
if($revision == $log->revision) $revisionName = $repo->SCM == 'Git' ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision;
|
||||
$log->committer = zget($commiters, $log->committer, $log->committer);
|
||||
$i++;
|
||||
}
|
||||
if(!isset($revisionName))
|
||||
{
|
||||
if($repo->SCM == 'Git') $gitCommit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch('commit');
|
||||
$revisionName = ($repo->SCM == 'Git' and isset($gitCommit)) ? $this->repo->getGitRevisionName($revision, $gitCommit) : $revision;
|
||||
}
|
||||
|
||||
$this->view->revisions = $revisions;
|
||||
$this->view->title = $this->lang->repo->common;
|
||||
$this->view->type = 'view';
|
||||
$this->view->showBug = $showBug;
|
||||
$this->view->encoding = str_replace('-', '_', $encoding);
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->repo = $repo;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->revisionName = $revisionName;
|
||||
$this->view->preAndNext = $this->repo->getPreAndNext($repo, '/' . $entry, $revision);
|
||||
$this->view->file = $file;
|
||||
$this->view->entry = $entry;
|
||||
$this->view->path = $entry;
|
||||
$this->view->suffix = $suffix;
|
||||
$this->view->content = $content;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->logType = $logType;
|
||||
$this->view->info = $info;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @param int $refresh
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($repoID = 0, $path = '', $revision = 'HEAD', $refresh = 0)
|
||||
{
|
||||
if($this->get->path) $path = $this->get->path;
|
||||
$this->locate($this->repo->createLink('log', "repoID=$repoID&entry=&revision=$revision", "entry=$path"));
|
||||
}
|
||||
|
||||
/**
|
||||
* show repo log.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @param string $type
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function log($repoID = 0, $entry = '', $revision = 'HEAD', $type = 'dir', $recTotal = 0, $recPerPage = 50, $pageID = 1)
|
||||
{
|
||||
if($this->get->entry) $entry = $this->get->entry;
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
$this->repo->setBackSession('list', $withOtherModule = true);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$file = $entry;
|
||||
$entry = $this->repo->decodePath($entry);
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$info = $this->scm->info($entry, $revision);
|
||||
|
||||
$logs = $this->repo->getLogs($repo, $entry, $revision, $type, $pager);
|
||||
$commiters = $this->loadModel('user')->getCommiters();
|
||||
foreach($logs as $log) $log->committer = zget($commiters, $log->committer, $log->committer);
|
||||
|
||||
$this->view->repo = $repo;
|
||||
$this->view->title = $this->lang->repo->common;
|
||||
$this->view->logs = $logs;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->entry = urldecode($entry);
|
||||
$this->view->path = urldecode($entry);
|
||||
$this->view->file = urldecode($file);
|
||||
$this->view->pager = $pager;
|
||||
$this->view->info = $info;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show repo revision.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param int $revision
|
||||
* @param string $path
|
||||
* @param string $type
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function revision($repoID, $revision, $root = '', $type = 'dir')
|
||||
{
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
$this->repo->setBackSession();
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$log = $this->scm->log('', $revision, $revision);
|
||||
|
||||
$history = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($log[0]->revision)->andWhere('repo')->eq($repoID)->fetch();
|
||||
if($history)
|
||||
{
|
||||
$oldRevision = $this->dao->select('revision')->from(TABLE_REPOHISTORY)->where('commit')->eq($history->commit - 1)->andWhere('repo')->eq($repoID)->fetch('revision');
|
||||
$log[0]->commit = $history->commit;
|
||||
}
|
||||
if(empty($oldRevision)) $oldRevision = '^';
|
||||
|
||||
$changes = array();
|
||||
$viewPriv = common::hasPriv('repo', 'view');
|
||||
$diffPriv = common::hasPriv('repo', 'diff');
|
||||
foreach($log[0]->change as $path => $change)
|
||||
{
|
||||
if($repo->prefix) $path = str_replace($repo->prefix, '', $path);
|
||||
$encodePath = $this->repo->encodePath($path);
|
||||
if($change['kind'] == '' or $change['kind'] == 'file')
|
||||
{
|
||||
$change['view'] = $viewPriv ? html::a($this->repo->createLink('view', "repoID=$repoID&entry=&revision=$revision", "entry=$encodePath"), $this->lang->repo->viewA) : '';
|
||||
if($change['action'] == 'M') $change['diff'] = $diffPriv ? html::a($this->repo->createLink('diff', "repoID=$repoID&entry=&oldRevision=$oldRevision&newRevision=$revision", "entry=$encodePath"), $this->lang->repo->diffAB) : '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$change['view'] = $viewPriv ? html::a($this->repo->createLink('log', "repoID=$repoID&entry=&revision=$revision", "entry=$encodePath"), $this->lang->repo->log) : '';
|
||||
if($change['action'] == 'M') $change['diff'] = $diffPriv ? html::a($this->repo->createLink('diff', "repoID=$repoID&entry=&oldRevision=$oldRevision&newRevision=$revision", "entry=$encodePath"), $this->lang->repo->diffAB) : '';
|
||||
}
|
||||
$changes[$path] = $change;
|
||||
}
|
||||
|
||||
$root = $this->repo->decodePath($root);
|
||||
$parent = '';
|
||||
if($type == 'file')
|
||||
{
|
||||
$parent = $this->dao->select('parent')->from(TABLE_REPOFILES)
|
||||
->where('revision')->eq($history->id)
|
||||
->andWhere('path')->eq('/' . $root)
|
||||
->fetch('parent');
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->common;
|
||||
$this->view->log = $log[0];
|
||||
$this->view->repo = $repo;
|
||||
$this->view->path = $root;
|
||||
$this->view->type = $type;
|
||||
$this->view->changes = $changes;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->revision = $log[0]->revision;
|
||||
$this->view->parentDir = $parent;
|
||||
$this->view->oldRevision = $oldRevision;
|
||||
$this->view->preAndNext = $this->repo->getPreAndNext($repo, $root, $revision, $type, 'revision');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show diff.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $oldRevision
|
||||
* @param string $newRevision
|
||||
* @param string $showBug
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function diff($repoID, $entry = '', $oldRevision = '0', $newRevision = 'HEAD', $showBug = 'false', $encoding = '')
|
||||
{
|
||||
if($this->get->entry) $entry = $this->get->entry;
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
$file = $entry;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$entry = $this->repo->decodePath($entry);
|
||||
|
||||
$pathInfo = pathinfo($entry);
|
||||
$suffix = '';
|
||||
if(isset($pathInfo["extension"])) $suffix = strtolower($pathInfo["extension"]);
|
||||
|
||||
$arrange = $this->cookie->arrange ? $this->cookie->arrange : 'inline';
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$oldRevision = isset($this->post->revision[1]) ?$this->post->revision[1] : '';
|
||||
$newRevision = isset($this->post->revision[0]) ?$this->post->revision[0] : '';
|
||||
if($this->post->arrange)
|
||||
{
|
||||
$arrange = $this->post->arrange;
|
||||
setcookie('arrange', $arrange);
|
||||
}
|
||||
if($this->post->encoding) $encoding = $this->post->encoding;
|
||||
if(!$oldRevision)
|
||||
{
|
||||
echo js::alert($this->lang->repo->error->diff);
|
||||
die(js::locate('back'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$encoding = empty($encoding) ? $repo->encoding : $encoding;
|
||||
$encoding = strtolower(str_replace('_', '-', $encoding));
|
||||
$info = $this->scm->info($entry, $newRevision);
|
||||
$diffs = $this->scm->diff($entry, $oldRevision, $newRevision);
|
||||
foreach($diffs as $diff)
|
||||
{
|
||||
if($encoding != 'utf-8')
|
||||
{
|
||||
$diff->fileName = helper::convertEncoding($diff->fileName, $encoding);
|
||||
if(empty($diff->contents)) continue;
|
||||
foreach($diff->contents as $content)
|
||||
{
|
||||
if(empty($content->lines)) continue;
|
||||
foreach($content->lines as $lines)
|
||||
{
|
||||
if(empty($lines->line)) continue;
|
||||
$lines->line = helper::convertEncoding($lines->line, $encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* When arrange is appose then adjust data for show them easy.*/
|
||||
if($arrange == 'appose')
|
||||
{
|
||||
foreach($diffs as $diffFile)
|
||||
{
|
||||
if(empty($diffFile->contents)) continue;
|
||||
foreach($diffFile->contents as $content)
|
||||
{
|
||||
$old = array();
|
||||
$new = array();
|
||||
foreach($content->lines as $line)
|
||||
{
|
||||
if($line->type != 'new') $old[$line->oldlc] = $line->line;
|
||||
if($line->type != 'old') $new[$line->newlc] = $line->line;
|
||||
}
|
||||
$content->old = $old;
|
||||
$content->new = $new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->diff;
|
||||
$this->view->position[] = $this->lang->repo->diff;
|
||||
|
||||
$this->view->type = 'diff';
|
||||
$this->view->showBug = $showBug;
|
||||
$this->view->entry = urldecode($entry);
|
||||
$this->view->suffix = $suffix;
|
||||
$this->view->file = $file;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->repo = $repo;
|
||||
$this->view->encoding = str_replace('-', '_', $encoding);
|
||||
$this->view->arrange = $arrange;
|
||||
$this->view->diffs = $diffs;
|
||||
$this->view->newRevision = $newRevision;
|
||||
$this->view->oldRevision = $oldRevision;
|
||||
$this->view->revision = $newRevision;
|
||||
$this->view->historys = $repo->SCM == 'Git' ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in("$oldRevision,$newRevision")->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
|
||||
$this->view->info = $info;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download repo file.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function download($repoID, $path, $fromRevision = 'HEAD', $toRevision = '', $type = 'file')
|
||||
{
|
||||
if($this->get->path) $path = $this->get->path;
|
||||
$entry = $this->repo->decodePath($path);
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$this->scm->setEngine($repo);
|
||||
$content = $type == 'file' ? $this->scm->cat($entry, $fromRevision) : $this->scm->diff($entry, $fromRevision, $toRevision, 'patch');
|
||||
$fileName = basename(urldecode($entry));
|
||||
if($type != 'file') $fileName .= "r$fromRevision--r$toRevision.patch";
|
||||
$extension = ltrim(strrchr($fileName, '.'), '.');
|
||||
$this->fetch('file', 'sendDownHeader', array("fileName" => $fileName, "fileType" => $extension, "content" => $content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show sync comment.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function showSyncComment($repoID = 0)
|
||||
{
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->showSyncComment;
|
||||
$this->view->position[] = $this->lang->repo->showSyncComment;
|
||||
|
||||
$latestInDB = $this->repo->getLatestComment($repoID);
|
||||
$this->view->version = $latestInDB ? (int)$latestInDB->commit : 1;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax sync comment.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxSyncComment($repoID = 0, $type = 'batch')
|
||||
{
|
||||
set_time_limit(0);
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
if(empty($repo)) die();
|
||||
if($repo->synced) die('finish');
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
|
||||
$branchID = '';
|
||||
if($repo->SCM == 'Git' and empty($branchID))
|
||||
{
|
||||
$branches = $this->scm->branch();
|
||||
if($branches)
|
||||
{
|
||||
/* Init branchID. */
|
||||
if($this->cookie->syncBranch) $branchID = $this->cookie->syncBranch;
|
||||
if(!isset($branches[$branchID])) $branchID = '';
|
||||
if(empty($branchID)) $branchID = reset($branches);
|
||||
|
||||
/* Get unsynced branches. */
|
||||
foreach($branches as $branch)
|
||||
{
|
||||
unset($branches[$branch]);
|
||||
if($branch == $branchID)
|
||||
{
|
||||
$this->repo->setRepoBranch($branchID);
|
||||
setcookie("syncBranch", $branchID, 0, $this->config->webRoot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$latestInDB = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($repo->SCM == 'Git' and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->orderBy('t1.time')
|
||||
->limit(1)
|
||||
->fetch();
|
||||
|
||||
$version = empty($latestInDB) ? 1 : $latestInDB->commit + 1;
|
||||
$logs = array();
|
||||
$revision = $version == 1 ? 'HEAD' : ($repo->SCM == 'Git' ? $latestInDB->commit : $latestInDB->revision);
|
||||
if($type == 'batch')
|
||||
{
|
||||
$logs = $this->scm->getCommits($revision, $this->config->repo->batchNum, $branchID);
|
||||
}
|
||||
else
|
||||
{
|
||||
$logs = $this->scm->getCommits($revision, 0, $branchID);
|
||||
}
|
||||
|
||||
$commitCount = $this->repo->saveCommit($repoID, $logs, $version, $branchID);
|
||||
if(empty($commitCount))
|
||||
{
|
||||
if(!$repo->synced)
|
||||
{
|
||||
if($repo->SCM == 'Git')
|
||||
{
|
||||
if($branchID) $this->repo->saveExistsLogBranch($repo->id, $branchID);
|
||||
|
||||
$branchID = reset($branches);
|
||||
setcookie("syncBranch", $branchID, 0, $this->config->webRoot);
|
||||
|
||||
if($branchID) $this->repo->fixCommit($repoID);
|
||||
}
|
||||
|
||||
if(empty($branchID))
|
||||
{
|
||||
$this->repo->markSynced($repoID);
|
||||
die('finish');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_REPO)->set('commits=commits + ' . $commitCount)->where('id')->eq($repoID)->exec();
|
||||
echo $type == 'batch' ? $commitCount : 'finish';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax show side logs.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $path
|
||||
* @param string $type
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxSideLogs($repoID, $path, $type = 'dir', $recTotal = 0, $recPerPage = 8, $pageID = 1)
|
||||
{
|
||||
if($this->get->path) $path = $this->get->path;
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$path = $this->repo->decodePath($path);
|
||||
$commiters = $this->loadModel('user')->getCommiters();
|
||||
$revisions = $this->repo->getLogs($repo, $path, 'HEAD', $type, $pager);
|
||||
foreach($revisions as $revision) $revision->committer = zget($commiters, $revision->committer, $revision->committer);
|
||||
|
||||
$this->view->repo = $this->repo->getRepoByID($repoID);
|
||||
$this->view->revisions = $revisions;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->logType = $type;
|
||||
$this->view->path = urldecode($path);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get committer.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param int $revision
|
||||
* @param int $line
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetCommitter($repoID, $entry, $revision, $line)
|
||||
{
|
||||
if($this->get->entry) $entry = $this->get->entry;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$entry = $this->repo->decodePath($entry);
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$blames = $this->scm->blame($entry, $revision);
|
||||
$committer = '';
|
||||
while($line > 0)
|
||||
{
|
||||
if(isset($blames[$line]['committer']))
|
||||
{
|
||||
$committer = $blames[$line]['committer'];
|
||||
break;
|
||||
}
|
||||
$line--;
|
||||
}
|
||||
die($committer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
a{color:#169;}
|
||||
a:hover, a:active{ text-decoration:underline; color:#C61A1A;}
|
||||
h2,h3 {font-size:20px; padding:0 0 10px; margin: 0; clear: both;}
|
||||
h3 {font-size:16px;}
|
||||
.revision{font-size:12px; line-height:20px; text-align:right; padding-right:8px;}
|
||||
.directory{ background-image:url('theme/default/images/repo/dir.png')}
|
||||
.file{ background-image:url('theme/default/images/repo/txt.png')}
|
||||
//.icon{ width:17px; padding-left:10px; padding-right:2px;}
|
||||
.mini-icon{ display: inline-block; height: 16px; width: 16px; background-color: transparent; background-position: 0 0; background-repeat: no-repeat; vertical-align: text-bottom;}
|
||||
.action {float:left;}
|
||||
.input-group select#encrypt{border-left:0px;}
|
||||
.arrange {float:right;}
|
||||
.versions {position:relative}
|
||||
#diffRepo {position:absolute; left:20px;z-index:1000;}
|
||||
#repoID {display: inline-block; width: auto;}
|
||||
.repoCode a:hover{text-decoration:none;}
|
||||
.commentButton
|
||||
{
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
left: -28px;
|
||||
width: 40px;
|
||||
z-index: 10;
|
||||
cursor:pointer;
|
||||
font-size:18px;
|
||||
color:#4183C4;
|
||||
display: none;
|
||||
}
|
||||
.repoCode tr.over .commentButton {display: block;}
|
||||
.bug
|
||||
{
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
left: -7px;
|
||||
width: 20px;
|
||||
z-index: 0;
|
||||
cursor:pointer;
|
||||
font-size:18px;
|
||||
color: #4183C4;
|
||||
line-height: 18px;
|
||||
}
|
||||
.repoCode .icon{opacity:1;}
|
||||
.icon-comment-add:before {content: '\e74c'; transform: scale(-1, 1); display: inline-block; font-weight: normal;}
|
||||
.icon-comment-add:after {content: '+'; display: block; font-weight: normal; position: absolute; left: 16px; top: 1px; font-family: Arial; font-weight: bold; font-size: 12px;}
|
||||
.icon-comments:before {content: '\e750'; transform: scale(-1, 1); display: inline-block; font-weight: normal; font-size: 18px; line-height: 18px;}
|
||||
.commentButton:hover,.bug:hover{color: #d20b0b;}
|
||||
.commentBoard{border-top: 1px solid #E4E4E4; border-bottom: 1px solid #E4E4E4; padding:0; white-space:normal; background-color:#eee; padding: 10px;}
|
||||
.commentBoard .table-form th {background: none}
|
||||
.lines input{width:40px;}
|
||||
.commentSubmit, .commentCancel{margin-right:10px;}
|
||||
.commentFoot .optional{float:left;}
|
||||
.commentBoard.using .bugContainer {border: 1px solid #ddd; background: #fff}
|
||||
.commentBoard.using .bugContainer > .commentHeader {background: #f1f1f1; padding: 0 10px; border-bottom: 1px solid #ddd}
|
||||
.commentHeaderAuthor{max-width: 600px; line-height: 33px; font-weight: bold; color: #222; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
|
||||
.comment{width:100%; word-break:keep-all; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
|
||||
.commentContent{margin:10px;}
|
||||
.commentHeaderRight{float:right;}
|
||||
|
||||
/* Sider */
|
||||
#mainContent > #sidebar > .side-body.affix {top:0px; z-index:10000;}
|
||||
|
||||
/* Pre row */
|
||||
.repoCode table > tbody > tr.over td {background: #f8eec7;}
|
||||
.repoCode table > tbody > tr.over th {background: #cdcdcd; color: #333}
|
||||
|
||||
/* Comment-btn */
|
||||
.comment-btn {position: relative; margin: 0; padding: 0; display: none}
|
||||
.repoCode tr.over .comment-btn {display: block;}
|
||||
.comment-btn .icon-wrapper {display: block; position: absolute; background: #4183C4; border-radius: 2px; width: 24px; height: 20px; left: -6px; top: 0; line-height: 20px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s;}
|
||||
.comment-btn .icon-wrapper:before {display: block; content: ' '; right: -4px; top: 6px; position: absolute; border-left: 4px solid #4183C4; border-right: 0 solid transparent; border-bottom: 4px solid transparent; border-top: 4px solid transparent; width: 0; height: 0}
|
||||
.comment-btn .icon-wrapper:hover {background: #169; transform: scale(1.1)}
|
||||
.comment-btn .icon-wrapper:hover:before {border-left-color: #169}
|
||||
|
||||
.repoCode tr.commented {cursor: pointer;}
|
||||
|
||||
.repoCode tr.commented .comment-btn {display: block;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper {background: none; border: none; width: 24px; line-height: 18px; height: 18px; left: -6px; color: #4183c4}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper:hover {border-color: #169; color: #169}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper > i:before {content: '\e750'; font-size: 18px; transform: scale(-1, 1); display: inline-block;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper:before {display: none}
|
||||
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper, .repoCode tr.selected.commented .comment-btn .icon-wrapper {line-height: 20px; height: 20px; background: #4183C4; color: #fff; left: -6px}
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper > i:before {content: "\e661"; font-size: 14px;}
|
||||
.repoCode tr.selected.commented .comment-btn .icon-wrapper > i:before {font-size: 14px;}
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper:before, .repoCode tr.selected.commented .comment-btn .icon-wrapper:before {display: block;}
|
||||
|
||||
/* repo action form */
|
||||
.repoCode .comment-list, .repoCode .comment-actions {max-width: 900px}
|
||||
.repoCode .bugFormContainer {border: 1px solid #bbb; margin: 0 0 0 15px; padding: 10px 20px 10px 10px; max-width: 880px; background: #fff}
|
||||
.repoCode .bugFormContainer th {width: 70px}
|
||||
|
||||
.repoCode .action-row {display: none}
|
||||
.repoCode .with-action-row .action-row {display: table-row}
|
||||
.repoCode .action-cell {background: #EEE; white-space: normal; padding: 10px 15px 10px 0;}
|
||||
.repoCode .with-action-row table tr.selected .comment-btn:last-child {display: block;}
|
||||
.repoCode .with-action-row table tr.selected td {background: #f8eec7}
|
||||
.repoCode .with-action-row table tr.selected th {background: #cdcdcd}
|
||||
.repoCode .with-action-row table tr.selected .comment-btn .icon-wrapper > i:before, .repoCode #diff.with-action-row tr.selected .comment-btn .icon-wrapper > i:before {content: '\d7'}
|
||||
|
||||
.repoCode .comment-row {display: none}
|
||||
.repoCode .comment-row.show {display: table-row !important;}
|
||||
.repoCode .comment-cell {background: #eee; white-space: normal;}
|
||||
.repoCode .comment-cell .panel {margin: 10px; border-color: #bbb}
|
||||
.repoCode .comment-cell .panel-body {padding: 6px 10px}
|
||||
.repoCode .comment-cell .panel-actions.pull-right {margin-right: 0; margin-top: 0;}
|
||||
.repoCode .comment-cell .editing .panel-body, .repoCode .comment-cell .commentContainer.show-form .panel-body {display: none}
|
||||
.repoCode .comment-cell .bug-edit-form, {padding: 10px; display: none}
|
||||
.repoCode .comment-cell .editing .bug-edit-form, .repoCode .comment-cell .commentContainer.show-form .comment-edit-form {display: block;}
|
||||
|
||||
.repoCode .comment {border: 1px solid #e5e5e5; background: #fafafa; padding: 5px 10px; margin-bottom: 10px;}
|
||||
.repoCode .comment .comment-edit-form {margin-top: 10px;}
|
||||
.repoCode .panel-bug .steps {background: #f1f1f1; padding: 5px 10px}
|
||||
.repoCode .panel-bug .bug-edit-form {margin-bottom: 10px;}
|
||||
.repoCode .panel-bug .panel-body {display: none}
|
||||
.repoCode .panel-bug .panel-heading {cursor: pointer;}
|
||||
.repoCode .panel-bug.show .panel-body {display: block;}
|
||||
.repoCode .panel-bug.show .icon-chevron-sign-down:before {content: '\e711'}
|
||||
.repoCode .panel-bug.show-edit-form .bug-edit-form,
|
||||
.repoCode .panel-bug.show-form .commentForm,
|
||||
.repoCode .comment.show-form .comment-edit-form {display: block;}
|
||||
.repoCode .panel-bug .bug-edit-form,
|
||||
.repoCode .panel-bug.show-form .addComment,
|
||||
.repoCode .panel-bug .commentForm,
|
||||
.repoCode .comment .comment-edit-form,
|
||||
.repoCode .panel-bug.show-edit-form .panel-body .title,
|
||||
.repoCode .panel-bug.show-edit-form .bug-date,
|
||||
.repoCode .comment.show-form .comment-content, .repoCode .comment.show-form .comment-date {display: none}
|
||||
|
||||
.repoCode .text-content {white-space: normal; white-space: pre-line}
|
||||
.repoCode .text-muted {color: #aaa}
|
||||
|
||||
.repoCode tr {transition: all 1s;}
|
||||
.repoCode tr.highlight {background: #fff4e5;}
|
||||
.repoCode tr.highlight td, .repoCode tr.highlight th {background: none; border-top: 1px solid #e48600; border-bottom: 1px solid #e48600}
|
||||
.repoCode tr.highlight.commented th {color: #e48600;}
|
||||
.repoCode tr.highlight.commented td, .repoCode tr.highlight.commented th {border-bottom: none}
|
||||
.repoCode tr.highlight + tr.highlight td, .repoCode tr.highlight + tr.highlight th {border-top: none}
|
||||
|
||||
.repoCode .row-tip {display: none;}
|
||||
.repoCode tr.commented .row-tip {display: block; position: relative; right: -3px; bottom: -1px;}
|
||||
.repoCode tr.commented .tip, .repoCode tr.commented.open .tip.on-collapse {display: block; position: absolute; right: 0; bottom: 0; color: #4183c4; opacity: 0; padding:0 5px; background: #edf3ff; height: 20px; line-height: 20px; transition: opacity 0.2s;}
|
||||
.repoCode tr.commented:hover .tip.on-expand {opacity: 1}
|
||||
.repoCode tr.commented.open .tip.on-collapse {opacity: 1}
|
||||
.repoCode tr.commented.open .tip.on-expand {display: none}
|
||||
.repoCode tr.commented.open .tip.on-collapse span {display: none}
|
||||
.repoCode tr.commented.open:hover .tip.on-collapse span {display: inline;}
|
||||
.repoCode tr.commented.open {background: #f8fafe}
|
||||
.repoCode tr.commented .preview-icon {position: absolute; left: -6px; bottom: 0; width: 20px; height: 20px; line-height: 20px; text-align: center; color: #4183c4; background: #edf3ff; display: none}
|
||||
.repoCode tr.commented:hover .preview-icon {display: block; transform: scale(-1, 1);}
|
||||
.repoCode tr.commented .preview-icon:before {font-size: 18px;}
|
||||
|
||||
.repoCode #diff tr.commented .row-tip {right: 0}
|
||||
.repoCode #diff tr.commented .icon-chat-dot {left: 0}
|
||||
|
||||
.repoCode .panel, .bugFormContainer {transition: border 0.4s;}
|
||||
.repoCode .panel.highlight, #bugForm.highlight .bugFormContainer {border-color: #e48600;}
|
||||
|
||||
#bugsPreview {white-space: normal;}
|
||||
#bugsPreview .dropdown-menu {top: -100%; left: 30%; padding-top: 0; min-width: 300px; max-width: 500px;}
|
||||
#bugsPreview .dropdown-menu > li.dropdown-header {background: #f1f1f1; padding-top: 8px;}
|
||||
#bugsPreview .dropdown-menu > li > a {border-top: 1px solid #e5e5e5; text-overflow : ellipsis; overflow: hidden;}
|
||||
#bugsPreview .dropdown-menu.show {display: block;}
|
||||
|
||||
.icon-comments {position: relative; left: -50px}
|
||||
|
||||
/* bug form */
|
||||
#bugForm, #bugForm table {margin: 0; padding: 0;}
|
||||
|
||||
.panel .table + .panel-footer {border-top: 0; background: #fff}
|
||||
|
||||
.transparent{ border-color:transparent;background: none repeat scroll 0 0 transparent;}
|
||||
.transparent:hover{ border-color:transparent;background: none repeat scroll 0 0 transparent;}
|
||||
|
||||
.side-col{width: 600px;}
|
||||
#sidebar > .side-body{width: 580px;}
|
||||
.hide-sidebar #sidebar > .side-body{display: none;}
|
||||
|
||||
#sidebar>.sidebar-toggle{left:5px; right:auto;}
|
||||
#sidebar>.sidebar-toggle>.icon{right:-4px; left:auto;}
|
||||
@@ -0,0 +1,22 @@
|
||||
body{padding-bottom:0px;}
|
||||
.w-code{ width:48%; word-break: break-all;}
|
||||
td.code { color:#484848; padding:0px 3px; white-space: pre-wrap}
|
||||
.none {background:#EAF2F5;}
|
||||
table.diff {margin-bottom:0px;}
|
||||
.diff caption{ border: 1px solid #e4e4e4; background: #edf3fe; margin: 0; padding: 6px 2px 6px 10px; text-align: left; font-weight: bold; font-size: 13px;}
|
||||
.diff th, .diff td{ border:none;}
|
||||
.diff th{ padding-top:2px; padding-bottom:2px;}
|
||||
.diff .line-new, .diff .line-new { background:#CFC;}
|
||||
.diff .line-old, .diff .line-old { background:#FCC;}
|
||||
.diff .line-all, .diff .line-all { background:#FFF;}
|
||||
.diff .w-num { width:25px; border-right:1px solid #E4E4E4; color:#999; border-left:1px solid #E4E4E4; color:#999; font-weight:normal;}
|
||||
|
||||
.repoCode .diff tr .comment-btn .icon-wrapper {left: -23px;}
|
||||
.repoCode .diff tr.over td.line-all, .repoCode .diff tr.over td.line-all {background: #f8eec7}
|
||||
.repoCode .diff tr.over td.line-new, .repoCode .diff tr.over td.line-new {background: #8eff8e}
|
||||
.repoCode .diff tr.over td.line-old, .repoCode .diff tr.over td.line-old {background: #f6b2b2}
|
||||
|
||||
.repoCode form > .btn {margin-right: 10px;}
|
||||
.label-exchange {background-color: #566F7C;cursor: pointer}
|
||||
.label-exchange i{padding:0;}
|
||||
.btn-download{border-right: none;}
|
||||
@@ -0,0 +1,3 @@
|
||||
.change ul{margin:8px;margin-left:1.5em;}
|
||||
.change li{ list-style:none;}
|
||||
.panel-heading {border-bottom: 1px solid #ddd;}
|
||||
@@ -0,0 +1,14 @@
|
||||
.code {position:relative; padding:3px; border-radius:3px;}
|
||||
.code .content {border:1px solid #CCC; padding:0;}
|
||||
.repoCode pre {margin:0;padding:0;background:white; border:none;}
|
||||
tr,th,td {border-bottom:none;}
|
||||
.repoCode pre > table > tbody > tr > th {border: none; background-color:#ECECEC; width: 40px; text-align:right; vertical-align: top;}
|
||||
.repoCode pre > table > tbody > tr > th, .repoCode pre > table > tbody > tr > td {padding:1px 3px;}
|
||||
.repoCode pre .commentContent{line-height:1.4;}
|
||||
.repoCode pre > table{border:0px; width:100%;}
|
||||
.repoCode .binary {text-align:center;}
|
||||
.repoCode .binary a {display:block; margin:100px 0px;}
|
||||
.repoCode .binary a .icon-download {font-size:50px;}
|
||||
.repoCode .image {text-align:center; padding-top:10px;}
|
||||
.panel .panel-heading .action .input-group {margin-top:-6px; margin-right:-10px;}
|
||||
.body-modal .panel-actions {right:30px;}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Swtich repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function switchRepo(repoID, module, method)
|
||||
{
|
||||
if(typeof(eventKeyCode) == 'undefined') eventKeyCode = 0;
|
||||
if(eventKeyCode > 0 && eventKeyCode != 13) return false;
|
||||
|
||||
/* The projec id is a string, use it as the project model. */
|
||||
if(isNaN(repoID))
|
||||
{
|
||||
$.cookie('projectMode', repoID, {expires:config.cookieLife, path:config.webRoot});
|
||||
repoID = 0;
|
||||
}
|
||||
|
||||
if(method != 'settings') method ="browse";
|
||||
link = createLink(module, method, 'repoID=' + repoID);
|
||||
location.href=link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch branch for git.
|
||||
*
|
||||
* @param string $branchID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function switchBranch(branchID)
|
||||
{
|
||||
$.cookie('repoBranch', branchID, {expires:config.cookieLife, path:config.webRoot});
|
||||
$.cookie('repoRefresh', 1, {expires:config.cookieLife, path:config.webRoot});
|
||||
location.href=location.href;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit select two.
|
||||
* @return void
|
||||
*/
|
||||
if($("input:checkbox[name='revision[]']:checked").length < 2)
|
||||
{
|
||||
$("input:checkbox[name='revision[]']:lt(2)").attr('checked', 'checked');
|
||||
}
|
||||
$("input:checkbox[name='revision[]']").each(function(){ if(!$(this).is(':checked')) $(this).attr("disabled","disabled")});
|
||||
$("input:checkbox[name='revision[]']").click(function(){
|
||||
var checkNum = $("input:checkbox[name='revision[]']:checked").length;
|
||||
if (checkNum >= 2)
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function(){ if(!$(this).is(':checked')) $(this).attr("disabled","disabled")});
|
||||
}
|
||||
else
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function(){$(this).attr("disabled", false)});
|
||||
}
|
||||
});
|
||||
|
||||
$(function()
|
||||
{
|
||||
$(document).on('click', '.ajaxPager', function()
|
||||
{
|
||||
$('#sidebar .side-body').load($(this).attr('href'));
|
||||
return false;
|
||||
})
|
||||
|
||||
if($('#sidebar').size() > 0)
|
||||
{
|
||||
var fixH = $("#sidebar").offset().top;
|
||||
$(window).scroll(function()
|
||||
{
|
||||
var scroH = $(this).scrollTop();
|
||||
if(scroH>=fixH)
|
||||
{
|
||||
$("#sidebar > .side-body").addClass('affix');
|
||||
}
|
||||
else if(scroH<fixH)
|
||||
{
|
||||
$("#sidebar > .side-body").removeClass('affix');
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
function changeEncoding(encoding)
|
||||
{
|
||||
$('#encoding').val(encoding);
|
||||
$('#encoding').parents('form').submit();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function()
|
||||
{
|
||||
$(this).click(function()
|
||||
{
|
||||
var checkNum = $("input:checkbox[name='revision[]']:checked").length;
|
||||
if (checkNum >= 2)
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function(){if($(this).attr('checked') == false) $(this).attr("disabled","disabled")});
|
||||
}
|
||||
else
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function(){if($(this).attr('checked') == false) $(this).attr("enabled","enabled")});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
var $pre = $('.repoCode .content pre');
|
||||
var rowTip = $('#rowTip').html();
|
||||
|
||||
if($pre.length)
|
||||
{
|
||||
hljs.initHighlightingOnLoad();
|
||||
var content = hljs.highlight($pre.attr('class'), $pre.text());
|
||||
var code = '', line;
|
||||
var arr = content.value.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/);
|
||||
for(var i = 0 ; i < arr.length ; i++)
|
||||
{
|
||||
line = i + 1;
|
||||
code += "<tr data-line='" + line +"'><th id='L" + line + "'><div class='comment-btn view'><span class='icon-wrapper'><i class='icon-plus'></i></span></div>" + line + "</th><td>" + (arr[i] || ' ') + rowTip + "</td></tr>";
|
||||
}
|
||||
$pre.html("<table><tbody>" + code + "</tbody></table>");
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
$lang->repo->common = 'Repo';
|
||||
$lang->repo->create = 'Create Repo';
|
||||
$lang->repo->settings = 'Settings';
|
||||
$lang->repo->browse = 'View Repo';
|
||||
$lang->repo->delete = 'Delete Repo';
|
||||
$lang->repo->showSyncComment = 'Display Synchronization';
|
||||
$lang->repo->ajaxSyncComment = 'Interface: Ajax Sync Note';
|
||||
$lang->repo->download = 'Download File';
|
||||
$lang->repo->downloadDiff = 'Download Diff';
|
||||
$lang->repo->diffAction = 'Revision Diff';
|
||||
$lang->repo->revisionAction = 'Revision Detail';
|
||||
$lang->repo->blameAction = 'Repo Blame';
|
||||
$lang->repo->addBug = 'Add Review';
|
||||
$lang->repo->editBug = 'Edit Bug';
|
||||
$lang->repo->deleteBug = 'Delete Bug';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
$lang->repo->editComment = 'Edit Comment';
|
||||
$lang->repo->deleteComment = 'Delete Comment';
|
||||
|
||||
$lang->repo->submit = 'Submit';
|
||||
$lang->repo->cancel = 'Cancel';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
|
||||
$lang->repo->product = $lang->productCommon;
|
||||
$lang->repo->module = 'Module';
|
||||
$lang->repo->project = $lang->projectCommon;
|
||||
$lang->repo->type = 'Type';
|
||||
$lang->repo->assign = 'AssignTo';
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->detile = 'Detail';
|
||||
$lang->repo->lines = 'Lines';
|
||||
$lang->repo->line = 'Line';
|
||||
$lang->repo->expand = 'Unfold';
|
||||
$lang->repo->collapse = 'Fold';
|
||||
|
||||
$lang->repo->id = 'ID';
|
||||
$lang->repo->SCM = 'Type';
|
||||
$lang->repo->name = 'Name';
|
||||
$lang->repo->path = 'Path';
|
||||
$lang->repo->prefix = 'Prefix';
|
||||
$lang->repo->config = 'Config';
|
||||
$lang->repo->account = 'Username';
|
||||
$lang->repo->password = 'Password';
|
||||
$lang->repo->encoding = 'Encoding';
|
||||
$lang->repo->client = 'Client Path';
|
||||
$lang->repo->size = 'Size';
|
||||
$lang->repo->revision = 'Revision';
|
||||
$lang->repo->revisionA = 'Revision';
|
||||
$lang->repo->revisions = 'Revision';
|
||||
$lang->repo->time = 'Date';
|
||||
$lang->repo->committer = 'Committer';
|
||||
$lang->repo->commits = 'Commits';
|
||||
$lang->repo->synced = 'Initialize Sync';
|
||||
$lang->repo->lastSync = 'Last Sync';
|
||||
$lang->repo->deleted = 'Deleted';
|
||||
$lang->repo->commit = 'Commit';
|
||||
$lang->repo->comment = 'Comment';
|
||||
$lang->repo->view = 'View File';
|
||||
$lang->repo->viewA = 'View';
|
||||
$lang->repo->log = 'Revision Log';
|
||||
$lang->repo->blame = 'Blame';
|
||||
$lang->repo->date = 'Date';
|
||||
$lang->repo->diff = 'Diff';
|
||||
$lang->repo->diffAB = 'Diff';
|
||||
$lang->repo->diffAll = 'Diff All';
|
||||
$lang->repo->viewDiff = 'View diff';
|
||||
$lang->repo->allLog = 'All Revisions';
|
||||
$lang->repo->location = 'Location';
|
||||
$lang->repo->file = 'File';
|
||||
$lang->repo->action = 'Action';
|
||||
$lang->repo->code = 'Code';
|
||||
$lang->repo->review = 'Repo Review';
|
||||
$lang->repo->acl = 'Privilege';
|
||||
$lang->repo->group = 'Group';
|
||||
$lang->repo->user = 'User';
|
||||
$lang->repo->info = 'Version Info';
|
||||
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->status = 'Status';
|
||||
$lang->repo->openedBy = 'CreatedBy';
|
||||
$lang->repo->assignedTo = 'AssignedTo';
|
||||
$lang->repo->openedDate = 'CreatedDate';
|
||||
|
||||
$lang->repo->latestRevision = 'Latest Revision';
|
||||
$lang->repo->actionInfo = "Add by %s in %s";
|
||||
$lang->repo->changes = "Change Log";
|
||||
$lang->repo->reviewLocation = "File: %s@%s, line:%s - %s";
|
||||
$lang->repo->commentEdit = '<i class="icon-pencil"></i>';
|
||||
$lang->repo->commentDelete = '<i class="icon-remove"></i>';
|
||||
$lang->repo->allChanges = "Other Changes";
|
||||
$lang->repo->commitTitle = "The %sth Commit";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = 'Inline';
|
||||
$lang->repo->viewDiffList['appose'] = 'Parallel';
|
||||
|
||||
$lang->repo->encryptList['plain'] = 'No encryption';
|
||||
$lang->repo->encryptList['base64'] = 'BASE64';
|
||||
|
||||
$lang->repo->logStyles['A'] = 'Add';
|
||||
$lang->repo->logStyles['M'] = 'Modification';
|
||||
$lang->repo->logStyles['D'] = 'Delete';
|
||||
|
||||
$lang->repo->encodingList['utf_8'] = 'UTF-8';
|
||||
$lang->repo->encodingList['gbk'] = 'GBK';
|
||||
|
||||
$lang->repo->scmList['Subversion'] = 'Subversion';
|
||||
$lang->repo->scmList['Git'] = 'Git';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = 'Synchronizing. Please wait ...';
|
||||
$lang->repo->notice->syncComplete = 'Synchronized. Now redirecting ...';
|
||||
$lang->repo->notice->syncedCount = 'The number of records synchronized is ';
|
||||
$lang->repo->notice->delete = 'Are you sure delete this repo?';
|
||||
$lang->repo->notice->successDelete = 'Repository is removed.';
|
||||
$lang->repo->notice->commentContent = 'Comment';
|
||||
$lang->repo->notice->deleteBug = 'Are you sure to delete this bug?';
|
||||
$lang->repo->notice->deleteComment = 'Are you sure to delete this comment?';
|
||||
$lang->repo->notice->lastSyncTime = 'Last Sync:';
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = 'Your server disabled exec and shell_exec, so it cannot be applied.';
|
||||
$lang->repo->error->connect = 'Connection to the repo failed. Please enter username, password and repo address correctly!';
|
||||
$lang->repo->error->version = 'Version 1.8+ of https and svn protocol is required. Please update to latest version! Go to http://subversion.apache.org/';
|
||||
$lang->repo->error->path = 'Repo address is the file path, e.g. /home/test.';
|
||||
$lang->repo->error->cmd = 'Client Error!';
|
||||
$lang->repo->error->diff = 'Two versions must be selected.';
|
||||
$lang->repo->error->product = "Please select {$lang->productCommon}!";
|
||||
$lang->repo->error->commentText = 'Please enter content for review!';
|
||||
$lang->repo->error->comment = 'Please enter content!';
|
||||
$lang->repo->error->title = 'Please enter title!';
|
||||
$lang->repo->error->accessDenied = 'You do not have the privilege to access the repository.';
|
||||
$lang->repo->error->noFound = 'The repo is not found.';
|
||||
$lang->repo->error->noFile = '%s does not exist.';
|
||||
$lang->repo->error->noPriv = 'The program does not have the privilege to switch to %s';
|
||||
$lang->repo->error->output = "The command is: %s\nThe error is(%s): %s\n";
|
||||
$lang->repo->error->clientVersion = "Client version is too low, please upgrade or change SVN client";
|
||||
$lang->repo->error->encoding = "The encoding maybe wrong. Please change the encoding and try again.";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = "For example, /usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git";
|
||||
$lang->repo->example->path = "For example, SVN: http://example.googlecode.com/svn/, GIT: /home/test";
|
||||
$lang->repo->example->config = "Config directory is required in https. Use '--config-dir' to generate config dir.";
|
||||
$lang->repo->example->encoding = "input encoding of files";
|
||||
|
||||
$lang->repo->typeList['standard'] = 'Standard';
|
||||
$lang->repo->typeList['performance'] = 'Performance';
|
||||
$lang->repo->typeList['security'] = 'Security';
|
||||
$lang->repo->typeList['redundancy'] = 'Redundancy';
|
||||
$lang->repo->typeList['logicError'] = 'Logic Error';
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
$lang->repo->common = 'Repo';
|
||||
$lang->repo->create = 'Create Repo';
|
||||
$lang->repo->settings = 'Settings';
|
||||
$lang->repo->browse = 'View Repo';
|
||||
$lang->repo->delete = 'Delete Repo';
|
||||
$lang->repo->showSyncComment = 'Display Synchronization';
|
||||
$lang->repo->ajaxSyncComment = 'Interface: Ajax Sync Note';
|
||||
$lang->repo->download = 'Download File';
|
||||
$lang->repo->downloadDiff = 'Download Diff';
|
||||
$lang->repo->diffAction = 'Revision Diff';
|
||||
$lang->repo->revisionAction = 'Revision Detail';
|
||||
$lang->repo->blameAction = 'Repo Blame';
|
||||
$lang->repo->addBug = 'Add Review';
|
||||
$lang->repo->editBug = 'Edit Bug';
|
||||
$lang->repo->deleteBug = 'Delete Bug';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
$lang->repo->editComment = 'Edit Comment';
|
||||
$lang->repo->deleteComment = 'Delete Comment';
|
||||
|
||||
$lang->repo->submit = 'Submit';
|
||||
$lang->repo->cancel = 'Cancel';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
|
||||
$lang->repo->product = $lang->productCommon;
|
||||
$lang->repo->module = 'Module';
|
||||
$lang->repo->project = $lang->projectCommon;
|
||||
$lang->repo->type = 'Type';
|
||||
$lang->repo->assign = 'AssignTo';
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->detile = 'Detail';
|
||||
$lang->repo->lines = 'Lines';
|
||||
$lang->repo->line = 'Line';
|
||||
$lang->repo->expand = 'Unfold';
|
||||
$lang->repo->collapse = 'Fold';
|
||||
|
||||
$lang->repo->id = 'ID';
|
||||
$lang->repo->SCM = 'Type';
|
||||
$lang->repo->name = 'Name';
|
||||
$lang->repo->path = 'Path';
|
||||
$lang->repo->prefix = 'Prefix';
|
||||
$lang->repo->config = 'Config';
|
||||
$lang->repo->account = 'Username';
|
||||
$lang->repo->password = 'Password';
|
||||
$lang->repo->encoding = 'Encoding';
|
||||
$lang->repo->client = 'Client Path';
|
||||
$lang->repo->size = 'Size';
|
||||
$lang->repo->revision = 'Revision';
|
||||
$lang->repo->revisionA = 'Revision';
|
||||
$lang->repo->revisions = 'Revision';
|
||||
$lang->repo->time = 'Date';
|
||||
$lang->repo->committer = 'Committer';
|
||||
$lang->repo->commits = 'Commits';
|
||||
$lang->repo->synced = 'Initialize Sync';
|
||||
$lang->repo->lastSync = 'Last Sync';
|
||||
$lang->repo->deleted = 'Deleted';
|
||||
$lang->repo->commit = 'Commit';
|
||||
$lang->repo->comment = 'Comment';
|
||||
$lang->repo->view = 'View File';
|
||||
$lang->repo->viewA = 'View';
|
||||
$lang->repo->log = 'Revision Log';
|
||||
$lang->repo->blame = 'Blame';
|
||||
$lang->repo->date = 'Date';
|
||||
$lang->repo->diff = 'Diff';
|
||||
$lang->repo->diffAB = 'Diff';
|
||||
$lang->repo->diffAll = 'Diff All';
|
||||
$lang->repo->viewDiff = 'View diff';
|
||||
$lang->repo->allLog = 'All Revisions';
|
||||
$lang->repo->location = 'Location';
|
||||
$lang->repo->file = 'File';
|
||||
$lang->repo->action = 'Action';
|
||||
$lang->repo->code = 'Code';
|
||||
$lang->repo->review = 'Repo Review';
|
||||
$lang->repo->acl = 'Privilege';
|
||||
$lang->repo->group = 'Group';
|
||||
$lang->repo->user = 'User';
|
||||
$lang->repo->info = 'Version Info';
|
||||
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->status = 'Status';
|
||||
$lang->repo->openedBy = 'CreatedBy';
|
||||
$lang->repo->assignedTo = 'AssignedTo';
|
||||
$lang->repo->openedDate = 'CreatedDate';
|
||||
|
||||
$lang->repo->latestRevision = 'Latest Revision';
|
||||
$lang->repo->actionInfo = "Add by %s in %s";
|
||||
$lang->repo->changes = "Change Log";
|
||||
$lang->repo->reviewLocation = "File: %s@%s, line:%s - %s";
|
||||
$lang->repo->commentEdit = '<i class="icon-pencil"></i>';
|
||||
$lang->repo->commentDelete = '<i class="icon-remove"></i>';
|
||||
$lang->repo->allChanges = "Other Changes";
|
||||
$lang->repo->commitTitle = "The %sth Commit";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = 'Inline';
|
||||
$lang->repo->viewDiffList['appose'] = 'Parallel';
|
||||
|
||||
$lang->repo->encryptList['plain'] = 'No encryption';
|
||||
$lang->repo->encryptList['base64'] = 'BASE64';
|
||||
|
||||
$lang->repo->logStyles['A'] = 'Add';
|
||||
$lang->repo->logStyles['M'] = 'Modification';
|
||||
$lang->repo->logStyles['D'] = 'Delete';
|
||||
|
||||
$lang->repo->encodingList['utf_8'] = 'UTF-8';
|
||||
$lang->repo->encodingList['gbk'] = 'GBK';
|
||||
|
||||
$lang->repo->scmList['Subversion'] = 'Subversion';
|
||||
$lang->repo->scmList['Git'] = 'Git';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = 'Synchronizing. Please wait ...';
|
||||
$lang->repo->notice->syncComplete = 'Synchronized. Now redirecting ...';
|
||||
$lang->repo->notice->syncedCount = 'The number of records synchronized is ';
|
||||
$lang->repo->notice->delete = 'Are you sure delete this repo?';
|
||||
$lang->repo->notice->successDelete = 'Repository is removed.';
|
||||
$lang->repo->notice->commentContent = 'Comment';
|
||||
$lang->repo->notice->deleteBug = 'Are you sure to delete this bug?';
|
||||
$lang->repo->notice->deleteComment = 'Are you sure to delete this comment?';
|
||||
$lang->repo->notice->lastSyncTime = 'Last Sync:';
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = 'Your server disabled exec and shell_exec, so it cannot be applied.';
|
||||
$lang->repo->error->connect = 'Connection to the repo failed. Please enter username, password and repo address correctly!';
|
||||
$lang->repo->error->version = 'Version 1.8+ of https and svn protocol is required. Please update to latest version! Go to http://subversion.apache.org/';
|
||||
$lang->repo->error->path = 'Repo address is the file path, e.g. /home/test.';
|
||||
$lang->repo->error->cmd = 'Client Error!';
|
||||
$lang->repo->error->diff = 'Two versions must be selected.';
|
||||
$lang->repo->error->product = "Please select {$lang->productCommon}!";
|
||||
$lang->repo->error->commentText = 'Please enter content for review!';
|
||||
$lang->repo->error->comment = 'Please enter content!';
|
||||
$lang->repo->error->title = 'Please enter title!';
|
||||
$lang->repo->error->accessDenied = 'You do not have the privilege to access the repository.';
|
||||
$lang->repo->error->noFound = 'The repo is not found.';
|
||||
$lang->repo->error->noFile = '%s does not exist.';
|
||||
$lang->repo->error->noPriv = 'The program does not have the privilege to switch to %s';
|
||||
$lang->repo->error->output = "The command is: %s\nThe error is(%s): %s\n";
|
||||
$lang->repo->error->clientVersion = "Client version is too low, please upgrade or change SVN client";
|
||||
$lang->repo->error->encoding = "The encoding maybe wrong. Please change the encoding and try again.";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = "For example, /usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git";
|
||||
$lang->repo->example->path = "For example, SVN: http://example.googlecode.com/svn/, GIT: /home/test";
|
||||
$lang->repo->example->config = "Config directory is required in https. Use '--config-dir' to generate config dir.";
|
||||
$lang->repo->example->encoding = "input encoding of files";
|
||||
|
||||
$lang->repo->typeList['standard'] = 'Standard';
|
||||
$lang->repo->typeList['performance'] = 'Performance';
|
||||
$lang->repo->typeList['security'] = 'Security';
|
||||
$lang->repo->typeList['redundancy'] = 'Redundancy';
|
||||
$lang->repo->typeList['logicError'] = 'Logic Error';
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
$lang->repo->common = 'Repo';
|
||||
$lang->repo->create = 'Create Repo';
|
||||
$lang->repo->settings = 'Settings';
|
||||
$lang->repo->browse = 'View Repo';
|
||||
$lang->repo->delete = 'Delete Repo';
|
||||
$lang->repo->showSyncComment = 'Display Synchronization';
|
||||
$lang->repo->ajaxSyncComment = 'Interface: Ajax Sync Note';
|
||||
$lang->repo->download = 'Download File';
|
||||
$lang->repo->downloadDiff = 'Download Diff';
|
||||
$lang->repo->diffAction = 'Revision Diff';
|
||||
$lang->repo->revisionAction = 'Revision Detail';
|
||||
$lang->repo->blameAction = 'Repo Blame';
|
||||
$lang->repo->addBug = 'Add Review';
|
||||
$lang->repo->editBug = 'Edit Bug';
|
||||
$lang->repo->deleteBug = 'Delete Bug';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
$lang->repo->editComment = 'Edit Comment';
|
||||
$lang->repo->deleteComment = 'Delete Comment';
|
||||
|
||||
$lang->repo->submit = 'Submit';
|
||||
$lang->repo->cancel = 'Cancel';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
|
||||
$lang->repo->product = $lang->productCommon;
|
||||
$lang->repo->module = 'Module';
|
||||
$lang->repo->project = $lang->projectCommon;
|
||||
$lang->repo->type = 'Type';
|
||||
$lang->repo->assign = 'AssignTo';
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->detile = 'Detail';
|
||||
$lang->repo->lines = 'Lines';
|
||||
$lang->repo->line = 'Line';
|
||||
$lang->repo->expand = 'Unfold';
|
||||
$lang->repo->collapse = 'Fold';
|
||||
|
||||
$lang->repo->id = 'ID';
|
||||
$lang->repo->SCM = 'Type';
|
||||
$lang->repo->name = 'Name';
|
||||
$lang->repo->path = 'Path';
|
||||
$lang->repo->prefix = 'Prefix';
|
||||
$lang->repo->config = 'Config';
|
||||
$lang->repo->account = 'Username';
|
||||
$lang->repo->password = 'Password';
|
||||
$lang->repo->encoding = 'Encoding';
|
||||
$lang->repo->client = 'Client Path';
|
||||
$lang->repo->size = 'Size';
|
||||
$lang->repo->revision = 'Revision';
|
||||
$lang->repo->revisionA = 'Revision';
|
||||
$lang->repo->revisions = 'Revision';
|
||||
$lang->repo->time = 'Date';
|
||||
$lang->repo->committer = 'Committer';
|
||||
$lang->repo->commits = 'Commits';
|
||||
$lang->repo->synced = 'Initialize Sync';
|
||||
$lang->repo->lastSync = 'Last Sync';
|
||||
$lang->repo->deleted = 'Deleted';
|
||||
$lang->repo->commit = 'Commit';
|
||||
$lang->repo->comment = 'Comment';
|
||||
$lang->repo->view = 'View File';
|
||||
$lang->repo->viewA = 'View';
|
||||
$lang->repo->log = 'Revision Log';
|
||||
$lang->repo->blame = 'Blame';
|
||||
$lang->repo->date = 'Date';
|
||||
$lang->repo->diff = 'Diff';
|
||||
$lang->repo->diffAB = 'Diff';
|
||||
$lang->repo->diffAll = 'Diff All';
|
||||
$lang->repo->viewDiff = 'View diff';
|
||||
$lang->repo->allLog = 'All Revisions';
|
||||
$lang->repo->location = 'Location';
|
||||
$lang->repo->file = 'File';
|
||||
$lang->repo->action = 'Action';
|
||||
$lang->repo->code = 'Code';
|
||||
$lang->repo->review = 'Repo Review';
|
||||
$lang->repo->acl = 'Privilege';
|
||||
$lang->repo->group = 'Group';
|
||||
$lang->repo->user = 'User';
|
||||
$lang->repo->info = 'Version Info';
|
||||
|
||||
$lang->repo->title = 'Title';
|
||||
$lang->repo->status = 'Status';
|
||||
$lang->repo->openedBy = 'CreatedBy';
|
||||
$lang->repo->assignedTo = 'AssignedTo';
|
||||
$lang->repo->openedDate = 'CreatedDate';
|
||||
|
||||
$lang->repo->latestRevision = 'Latest Revision';
|
||||
$lang->repo->actionInfo = "Add by %s in %s";
|
||||
$lang->repo->changes = "Change Log";
|
||||
$lang->repo->reviewLocation = "File: %s@%s, line:%s - %s";
|
||||
$lang->repo->commentEdit = '<i class="icon-pencil"></i>';
|
||||
$lang->repo->commentDelete = '<i class="icon-remove"></i>';
|
||||
$lang->repo->allChanges = "Other Changes";
|
||||
$lang->repo->commitTitle = "The %sth Commit";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = 'Inline';
|
||||
$lang->repo->viewDiffList['appose'] = 'Parallel';
|
||||
|
||||
$lang->repo->encryptList['plain'] = 'No encryption';
|
||||
$lang->repo->encryptList['base64'] = 'BASE64';
|
||||
|
||||
$lang->repo->logStyles['A'] = 'Add';
|
||||
$lang->repo->logStyles['M'] = 'Modification';
|
||||
$lang->repo->logStyles['D'] = 'Delete';
|
||||
|
||||
$lang->repo->encodingList['utf_8'] = 'UTF-8';
|
||||
$lang->repo->encodingList['gbk'] = 'GBK';
|
||||
|
||||
$lang->repo->scmList['Subversion'] = 'Subversion';
|
||||
$lang->repo->scmList['Git'] = 'Git';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = 'Synchronizing. Please wait ...';
|
||||
$lang->repo->notice->syncComplete = 'Synchronized. Now redirecting ...';
|
||||
$lang->repo->notice->syncedCount = 'The number of records synchronized is ';
|
||||
$lang->repo->notice->delete = 'Are you sure delete this repo?';
|
||||
$lang->repo->notice->successDelete = 'Repository is removed.';
|
||||
$lang->repo->notice->commentContent = 'Comment';
|
||||
$lang->repo->notice->deleteBug = 'Are you sure to delete this bug?';
|
||||
$lang->repo->notice->deleteComment = 'Are you sure to delete this comment?';
|
||||
$lang->repo->notice->lastSyncTime = 'Last Sync:';
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = 'Your server disabled exec and shell_exec, so it cannot be applied.';
|
||||
$lang->repo->error->connect = 'Connection to the repo failed. Please enter username, password and repo address correctly!';
|
||||
$lang->repo->error->version = 'Version 1.8+ of https and svn protocol is required. Please update to latest version! Go to http://subversion.apache.org/';
|
||||
$lang->repo->error->path = 'Repo address is the file path, e.g. /home/test.';
|
||||
$lang->repo->error->cmd = 'Client Error!';
|
||||
$lang->repo->error->diff = 'Two versions must be selected.';
|
||||
$lang->repo->error->product = "Please select {$lang->productCommon}!";
|
||||
$lang->repo->error->commentText = 'Please enter content for review!';
|
||||
$lang->repo->error->comment = 'Please enter content!';
|
||||
$lang->repo->error->title = 'Please enter title!';
|
||||
$lang->repo->error->accessDenied = 'You do not have the privilege to access the repository.';
|
||||
$lang->repo->error->noFound = 'The repo is not found.';
|
||||
$lang->repo->error->noFile = '%s does not exist.';
|
||||
$lang->repo->error->noPriv = 'The program does not have the privilege to switch to %s';
|
||||
$lang->repo->error->output = "The command is: %s\nThe error is(%s): %s\n";
|
||||
$lang->repo->error->clientVersion = "Client version is too low, please upgrade or change SVN client";
|
||||
$lang->repo->error->encoding = "The encoding maybe wrong. Please change the encoding and try again.";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = "For example, /usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git";
|
||||
$lang->repo->example->path = "For example, SVN: http://example.googlecode.com/svn/, GIT: /home/test";
|
||||
$lang->repo->example->config = "Config directory is required in https. Use '--config-dir' to generate config dir.";
|
||||
$lang->repo->example->encoding = "input encoding of files";
|
||||
|
||||
$lang->repo->typeList['standard'] = 'Standard';
|
||||
$lang->repo->typeList['performance'] = 'Performance';
|
||||
$lang->repo->typeList['security'] = 'Security';
|
||||
$lang->repo->typeList['redundancy'] = 'Redundancy';
|
||||
$lang->repo->typeList['logicError'] = 'Logic Error';
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
$lang->repo->common = '代码';
|
||||
$lang->repo->create = '创建版本库';
|
||||
$lang->repo->settings = '版本库设置';
|
||||
$lang->repo->browse = '浏览';
|
||||
$lang->repo->delete = '删除版本库';
|
||||
$lang->repo->showSyncComment = '显示同步进度';
|
||||
$lang->repo->ajaxSyncComment = '接口:AJAX同步注释';
|
||||
$lang->repo->download = '下载';
|
||||
$lang->repo->downloadDiff = '下载Diff';
|
||||
$lang->repo->diffAction = '版本对比';
|
||||
$lang->repo->revisionAction = '版本详情';
|
||||
$lang->repo->blameAction = '版本追溯';
|
||||
$lang->repo->addBug = '添加评审';
|
||||
$lang->repo->editBug = '编辑评审';
|
||||
$lang->repo->deleteBug = '删除评审';
|
||||
$lang->repo->addComment = '添加备注';
|
||||
$lang->repo->editComment = '编辑备注';
|
||||
$lang->repo->deleteComment = '删除备注';
|
||||
|
||||
$lang->repo->submit = '提交';
|
||||
$lang->repo->cancel = '取消';
|
||||
$lang->repo->addComment = '添加评论';
|
||||
|
||||
$lang->repo->product = $lang->productCommon;
|
||||
$lang->repo->module = '模块';
|
||||
$lang->repo->project = $lang->projectCommon;
|
||||
$lang->repo->type = '类型';
|
||||
$lang->repo->assign = '指派';
|
||||
$lang->repo->title = '标题';
|
||||
$lang->repo->detile = '详情';
|
||||
$lang->repo->lines = '代码行';
|
||||
$lang->repo->line = '行';
|
||||
$lang->repo->expand = '点击展开';
|
||||
$lang->repo->collapse = '点击折叠';
|
||||
|
||||
$lang->repo->id = '编号';
|
||||
$lang->repo->SCM = '类型';
|
||||
$lang->repo->name = '名称';
|
||||
$lang->repo->path = '地址';
|
||||
$lang->repo->prefix = '地址扩展';
|
||||
$lang->repo->config = '配置目录';
|
||||
$lang->repo->account = '用户名';
|
||||
$lang->repo->password = '密码';
|
||||
$lang->repo->encoding = '编码';
|
||||
$lang->repo->client = '客户端';
|
||||
$lang->repo->size = '大小';
|
||||
$lang->repo->revision = '查看版本';
|
||||
$lang->repo->revisionA = '版本';
|
||||
$lang->repo->revisions = '版本';
|
||||
$lang->repo->time = '提交时间';
|
||||
$lang->repo->committer = '作者';
|
||||
$lang->repo->commits = '提交数';
|
||||
$lang->repo->synced = '初始化同步';
|
||||
$lang->repo->lastSync = '最后同步时间';
|
||||
$lang->repo->deleted = '已删除';
|
||||
$lang->repo->commit = '提交';
|
||||
$lang->repo->comment = '注释';
|
||||
$lang->repo->view = '查看文件';
|
||||
$lang->repo->viewA = '查看';
|
||||
$lang->repo->log = '版本历史';
|
||||
$lang->repo->blame = '追溯';
|
||||
$lang->repo->date = '日期';
|
||||
$lang->repo->diff = '比较差异';
|
||||
$lang->repo->diffAB = '比较';
|
||||
$lang->repo->diffAll = '全部比较';
|
||||
$lang->repo->viewDiff = '查看差异';
|
||||
$lang->repo->allLog = '所有版本';
|
||||
$lang->repo->location = '位置';
|
||||
$lang->repo->file = '文件';
|
||||
$lang->repo->action = '操作';
|
||||
$lang->repo->code = '代码';
|
||||
$lang->repo->review = '评审';
|
||||
$lang->repo->acl = '权限';
|
||||
$lang->repo->group = '分组';
|
||||
$lang->repo->user = '用户';
|
||||
$lang->repo->info = '版本信息';
|
||||
|
||||
$lang->repo->title = '标题';
|
||||
$lang->repo->status = '状态';
|
||||
$lang->repo->openedBy = '创建者';
|
||||
$lang->repo->assignedTo = '指派给';
|
||||
$lang->repo->openedDate = '创建日期';
|
||||
|
||||
$lang->repo->latestRevision = '最近修订版本';
|
||||
$lang->repo->actionInfo = "由%s在%s添加";
|
||||
$lang->repo->changes = "修改记录";
|
||||
$lang->repo->reviewLocation = "%s@%s,%s行 - %s行";
|
||||
$lang->repo->commentEdit = '<i class="icon-pencil"></i>';
|
||||
$lang->repo->commentDelete = '<i class="icon-remove"></i>';
|
||||
$lang->repo->allChanges = "其他改动";
|
||||
$lang->repo->commitTitle = "第%s次提交";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = '直列';
|
||||
$lang->repo->viewDiffList['appose'] = '并排';
|
||||
|
||||
$lang->repo->encryptList['plain'] = '不加密';
|
||||
$lang->repo->encryptList['base64'] = 'BASE64';
|
||||
|
||||
$lang->repo->logStyles['A'] = '添加';
|
||||
$lang->repo->logStyles['M'] = '修改';
|
||||
$lang->repo->logStyles['D'] = '删除';
|
||||
|
||||
$lang->repo->encodingList['utf_8'] = 'UTF-8';
|
||||
$lang->repo->encodingList['gbk'] = 'GBK';
|
||||
|
||||
$lang->repo->scmList['Subversion'] = 'Subversion';
|
||||
$lang->repo->scmList['Git'] = 'Git';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = '正在同步中, 请稍等...';
|
||||
$lang->repo->notice->syncComplete = '同步完成,正在跳转...';
|
||||
$lang->repo->notice->syncedCount = '已经同步记录条数';
|
||||
$lang->repo->notice->delete = '是否要删除该版本库?';
|
||||
$lang->repo->notice->successDelete = '已经成功删除版本库。';
|
||||
$lang->repo->notice->commentContent = '输入回复内容';
|
||||
$lang->repo->notice->deleteBug = '确认删除该Bug?';
|
||||
$lang->repo->notice->deleteComment = '确认删除该回复?';
|
||||
$lang->repo->notice->lastSyncTime = '最后更新于:';
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = '你的服务器禁用了exec,shell_exec方法,无法使用该功能';
|
||||
$lang->repo->error->connect = '连接版本库失败,请填写正确的用户名、密码和版本库地址!';
|
||||
$lang->repo->error->version = "https和svn协议需要1.8及以上版本的客户端,请升级到最新版本!详情访问:http://subversion.apache.org/";
|
||||
$lang->repo->error->path = '版本库地址直接填写文件路径,如:/home/test。';
|
||||
$lang->repo->error->cmd = '客户端错误!';
|
||||
$lang->repo->error->diff = '必须选择两个版本';
|
||||
$lang->repo->error->product = "请选择{$lang->productCommon}!";
|
||||
$lang->repo->error->commentText = '请填写评审内容';
|
||||
$lang->repo->error->comment = '请填写内容';
|
||||
$lang->repo->error->title = '请填写标题';
|
||||
$lang->repo->error->accessDenied = '你没有权限访问该版本库';
|
||||
$lang->repo->error->noFound = '你访问的版本库不存在';
|
||||
$lang->repo->error->noFile = '目录 %s 不存在';
|
||||
$lang->repo->error->noPriv = '程序没有权限切换到目录 %s';
|
||||
$lang->repo->error->output = "执行命令:%s\n错误结果(%s): %s\n";
|
||||
$lang->repo->error->clientVersion = "客户端版本过低,请升级或更换SVN客户端";
|
||||
$lang->repo->error->encoding = "编码可能错误,请更换编码重试。";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = "例如:/usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git";
|
||||
$lang->repo->example->path = "例如:SVN: http://example.googlecode.com/svn/, GIT: /homt/test";
|
||||
$lang->repo->example->config = "https需要填写配置目录的位置,通过config-dir选项生成配置目录";
|
||||
$lang->repo->example->encoding = "填写版本库中文件的编码";
|
||||
|
||||
$lang->repo->typeList['standard'] = '规范';
|
||||
$lang->repo->typeList['performance'] = '性能';
|
||||
$lang->repo->typeList['security'] = '安全';
|
||||
$lang->repo->typeList['redundancy'] = '冗余';
|
||||
$lang->repo->typeList['logicError'] = '逻辑错误';
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
$lang->repo->common = '代碼';
|
||||
$lang->repo->create = '創建版本庫';
|
||||
$lang->repo->settings = '版本庫設置';
|
||||
$lang->repo->browse = '瀏覽';
|
||||
$lang->repo->delete = '刪除版本庫';
|
||||
$lang->repo->showSyncComment = '顯示同步進度';
|
||||
$lang->repo->ajaxSyncComment = '介面:AJAX同步註釋';
|
||||
$lang->repo->download = '下載';
|
||||
$lang->repo->downloadDiff = '下載Diff';
|
||||
$lang->repo->diffAction = '版本對比';
|
||||
$lang->repo->revisionAction = '版本詳情';
|
||||
$lang->repo->blameAction = '版本追溯';
|
||||
$lang->repo->addBug = '添加評審';
|
||||
$lang->repo->editBug = '編輯評審';
|
||||
$lang->repo->deleteBug = '刪除評審';
|
||||
$lang->repo->addComment = '添加備註';
|
||||
$lang->repo->editComment = '編輯備註';
|
||||
$lang->repo->deleteComment = '刪除備註';
|
||||
|
||||
$lang->repo->submit = '提交';
|
||||
$lang->repo->cancel = '取消';
|
||||
$lang->repo->addComment = '添加評論';
|
||||
|
||||
$lang->repo->product = $lang->productCommon;
|
||||
$lang->repo->module = '模組';
|
||||
$lang->repo->project = $lang->projectCommon;
|
||||
$lang->repo->type = '類型';
|
||||
$lang->repo->assign = '指派';
|
||||
$lang->repo->title = '標題';
|
||||
$lang->repo->detile = '詳情';
|
||||
$lang->repo->lines = '代碼行';
|
||||
$lang->repo->line = '行';
|
||||
$lang->repo->expand = '點擊展開';
|
||||
$lang->repo->collapse = '點擊摺疊';
|
||||
|
||||
$lang->repo->id = '編號';
|
||||
$lang->repo->SCM = '類型';
|
||||
$lang->repo->name = '名稱';
|
||||
$lang->repo->path = '地址';
|
||||
$lang->repo->prefix = '地址擴展';
|
||||
$lang->repo->config = '配置目錄';
|
||||
$lang->repo->account = '用戶名';
|
||||
$lang->repo->password = '密碼';
|
||||
$lang->repo->encoding = '編碼';
|
||||
$lang->repo->client = '客戶端';
|
||||
$lang->repo->size = '大小';
|
||||
$lang->repo->revision = '查看版本';
|
||||
$lang->repo->revisionA = '版本';
|
||||
$lang->repo->revisions = '版本';
|
||||
$lang->repo->time = '提交時間';
|
||||
$lang->repo->committer = '作者';
|
||||
$lang->repo->commits = '提交數';
|
||||
$lang->repo->synced = '初始化同步';
|
||||
$lang->repo->lastSync = '最後同步時間';
|
||||
$lang->repo->deleted = '已刪除';
|
||||
$lang->repo->commit = '提交';
|
||||
$lang->repo->comment = '註釋';
|
||||
$lang->repo->view = '查看檔案';
|
||||
$lang->repo->viewA = '查看';
|
||||
$lang->repo->log = '版本歷史';
|
||||
$lang->repo->blame = '追溯';
|
||||
$lang->repo->date = '日期';
|
||||
$lang->repo->diff = '比較差異';
|
||||
$lang->repo->diffAB = '比較';
|
||||
$lang->repo->diffAll = '全部比較';
|
||||
$lang->repo->viewDiff = '查看差異';
|
||||
$lang->repo->allLog = '所有版本';
|
||||
$lang->repo->location = '位置';
|
||||
$lang->repo->file = '檔案';
|
||||
$lang->repo->action = '操作';
|
||||
$lang->repo->code = '代碼';
|
||||
$lang->repo->review = '評審';
|
||||
$lang->repo->acl = '權限';
|
||||
$lang->repo->group = '分組';
|
||||
$lang->repo->user = '用戶';
|
||||
$lang->repo->info = '版本信息';
|
||||
|
||||
$lang->repo->title = '標題';
|
||||
$lang->repo->status = '狀態';
|
||||
$lang->repo->openedBy = '創建者';
|
||||
$lang->repo->assignedTo = '指派給';
|
||||
$lang->repo->openedDate = '創建日期';
|
||||
|
||||
$lang->repo->latestRevision = '最近修訂版本';
|
||||
$lang->repo->actionInfo = "由%s在%s添加";
|
||||
$lang->repo->changes = "修改記錄";
|
||||
$lang->repo->reviewLocation = "%s@%s,%s行 - %s行";
|
||||
$lang->repo->commentEdit = '<i class="icon-pencil"></i>';
|
||||
$lang->repo->commentDelete = '<i class="icon-remove"></i>';
|
||||
$lang->repo->allChanges = "其他改動";
|
||||
$lang->repo->commitTitle = "第%s次提交";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = '直列';
|
||||
$lang->repo->viewDiffList['appose'] = '並排';
|
||||
|
||||
$lang->repo->encryptList['plain'] = '不加密';
|
||||
$lang->repo->encryptList['base64'] = 'BASE64';
|
||||
|
||||
$lang->repo->logStyles['A'] = '添加';
|
||||
$lang->repo->logStyles['M'] = '修改';
|
||||
$lang->repo->logStyles['D'] = '刪除';
|
||||
|
||||
$lang->repo->encodingList['utf_8'] = 'UTF-8';
|
||||
$lang->repo->encodingList['gbk'] = 'GBK';
|
||||
|
||||
$lang->repo->scmList['Subversion'] = 'Subversion';
|
||||
$lang->repo->scmList['Git'] = 'Git';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = '正在同步中, 請稍等...';
|
||||
$lang->repo->notice->syncComplete = '同步完成,正在跳轉...';
|
||||
$lang->repo->notice->syncedCount = '已經同步記錄條數';
|
||||
$lang->repo->notice->delete = '是否要刪除該版本庫?';
|
||||
$lang->repo->notice->successDelete = '已經成功刪除版本庫。';
|
||||
$lang->repo->notice->commentContent = '輸入回覆內容';
|
||||
$lang->repo->notice->deleteBug = '確認刪除該Bug?';
|
||||
$lang->repo->notice->deleteComment = '確認刪除該回覆?';
|
||||
$lang->repo->notice->lastSyncTime = '最後更新于:';
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = '你的伺服器禁用了exec,shell_exec方法,無法使用該功能';
|
||||
$lang->repo->error->connect = '連接版本庫失敗,請填寫正確的用戶名、密碼和版本庫地址!';
|
||||
$lang->repo->error->version = "https和svn協議需要1.8及以上版本的客戶端,請升級到最新版本!詳情訪問:http://subversion.apache.org/";
|
||||
$lang->repo->error->path = '版本庫地址直接填寫檔案路徑,如:/home/test。';
|
||||
$lang->repo->error->cmd = '客戶端錯誤!';
|
||||
$lang->repo->error->diff = '必須選擇兩個版本';
|
||||
$lang->repo->error->product = "請選擇{$lang->productCommon}!";
|
||||
$lang->repo->error->commentText = '請填寫評審內容';
|
||||
$lang->repo->error->comment = '請填寫內容';
|
||||
$lang->repo->error->title = '請填寫標題';
|
||||
$lang->repo->error->accessDenied = '你沒有權限訪問該版本庫';
|
||||
$lang->repo->error->noFound = '你訪問的版本庫不存在';
|
||||
$lang->repo->error->noFile = '目錄 %s 不存在';
|
||||
$lang->repo->error->noPriv = '程序沒有權限切換到目錄 %s';
|
||||
$lang->repo->error->output = "執行命令:%s\n錯誤結果(%s): %s\n";
|
||||
$lang->repo->error->clientVersion = "客戶端版本過低,請升級或更換SVN客戶端";
|
||||
$lang->repo->error->encoding = "編碼可能錯誤,請更換編碼重試。";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = "例如:/usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git";
|
||||
$lang->repo->example->path = "例如:SVN: http://example.googlecode.com/svn/, GIT: /homt/test";
|
||||
$lang->repo->example->config = "https需要填寫配置目錄的位置,通過config-dir選項生成配置目錄";
|
||||
$lang->repo->example->encoding = "填寫版本庫中檔案的編碼";
|
||||
|
||||
$lang->repo->typeList['standard'] = '規範';
|
||||
$lang->repo->typeList['performance'] = '性能';
|
||||
$lang->repo->typeList['security'] = '安全';
|
||||
$lang->repo->typeList['redundancy'] = '冗餘';
|
||||
$lang->repo->typeList['logicError'] = '邏輯錯誤';
|
||||
@@ -0,0 +1,964 @@
|
||||
<?php
|
||||
class repoModel extends model
|
||||
{
|
||||
/**
|
||||
* Check repo priv.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkPriv($repo)
|
||||
{
|
||||
$account = $this->app->user->account;
|
||||
if(strpos(",{$this->app->company->admins},", ",$account,") !== false) return true;
|
||||
if(empty($repo->acl->groups) and empty($repo->acl->users)) return true;
|
||||
if(!empty($repo->acl->groups))
|
||||
{
|
||||
foreach($this->app->user->groups as $group)
|
||||
{
|
||||
if(in_array($group, $repo->acl->groups)) return true;
|
||||
}
|
||||
}
|
||||
if(!empty($repo->acl->users) and in_array($account, $repo->acl->users)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu.
|
||||
*
|
||||
* @param array $repos
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMenu($repos, $repoID = '')
|
||||
{
|
||||
if(empty($repoID)) $repoID = $this->session->repoID ? $this->session->repoID : key($repos);
|
||||
if(!isset($repos[$repoID])) $repoID = key($repos);
|
||||
|
||||
/* Check the privilege. */
|
||||
if($repoID)
|
||||
{
|
||||
$repo = $this->getRepoByID($repoID);
|
||||
if(empty($repo))
|
||||
{
|
||||
echo(js::alert($this->lang->repo->error->noFound));
|
||||
die(js::locate('back'));
|
||||
}
|
||||
|
||||
if(!$this->checkPriv($repo))
|
||||
{
|
||||
echo(js::alert($this->lang->repo->error->accessDenied));
|
||||
die(js::locate('back'));
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($repos))
|
||||
{
|
||||
$repoIndex = '<div class="btn-group angle-btn"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . ($repo->SCM == 'Subversion' ? '[SVN] ' : '[GIT] ') . $repo->name . ' <span class="caret"></span></button>';
|
||||
$repoIndex .= $this->select($repos, $repoID);
|
||||
$repoIndex .= '</div></div>';
|
||||
|
||||
$branches = $this->getBranches($repo);
|
||||
if(empty($branches))
|
||||
{
|
||||
$this->setRepoBranch('');
|
||||
}
|
||||
else
|
||||
{
|
||||
$branchID = 'master';
|
||||
if($this->cookie->repoBranch) $branchID = $this->cookie->repoBranch;
|
||||
if(!isset($branches[$branchID])) $branchID = 'master';
|
||||
|
||||
$branch = zget($branches, $branchID);
|
||||
if(empty($branch)) $branchID = $branch = current($branches);
|
||||
|
||||
$this->setRepoBranch($branchID);
|
||||
|
||||
$repoIndex .= '<div class="btn-group angle-btn"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . $branch . ' <span class="caret"></span></button>';
|
||||
$repoIndex .= "<div class='dropdown-menu search-list' data-ride='searchList'>";
|
||||
$repoIndex .= "<div class='list-group'>";
|
||||
foreach($branches as $branch)
|
||||
{
|
||||
$class = $branchID == $branch ? "class='active'" : '';
|
||||
$repoIndex .= html::a("javascript:switchBranch(\"$branch\")", $branch, '', $class);
|
||||
}
|
||||
$repoIndex .= "</div></div></div></div>";
|
||||
}
|
||||
|
||||
$this->lang->modulePageNav = $repoIndex;
|
||||
}
|
||||
|
||||
foreach($this->lang->repo->menu as $key => $menu)
|
||||
{
|
||||
common::setMenuVars($this->lang->repo->menu, $key, $repoID);
|
||||
}
|
||||
|
||||
session_start();
|
||||
$this->session->set('repoID', $repoID);
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the select code of repos.
|
||||
*
|
||||
* @param array $repos
|
||||
* @param int $repoID
|
||||
* @param string $currentModule
|
||||
* @param string $currentMethod
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function select($repos, $repoID)
|
||||
{
|
||||
$selectHtml = "<div class='dropdown-menu search-list' data-ride='searchList'>";
|
||||
$selectHtml .= "<div class='input-control search-box has-icon-left has-icon-right search-example'>";
|
||||
$selectHtml .= "<input id='repoSearchBox' type='search' autocomplete='off' class='form-control search-input empty'>";
|
||||
$selectHtml .= "<label for='repoSearchBox' class='input-control-icon-left search-icon'><i class='icon icon-search'></i></label>";
|
||||
$selectHtml .= "<a class='input-control-icon-right search-clear-btn'><i class='icon icon-close icon-sm'></i></a></div>";
|
||||
$selectHtml .= "<div class='list-group'>";
|
||||
foreach($repos as $id => $name)
|
||||
{
|
||||
$class = $repoID == $id ? "class='active'" : '';
|
||||
$selectHtml .= html::a(helper::createLink('repo', 'log', "repoID={$id}"), $name, '', $class);
|
||||
}
|
||||
$selectHtml .= "</div></div>";
|
||||
|
||||
return $selectHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all repos.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getAllRepos()
|
||||
{
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq(0)->fetchAll();
|
||||
foreach($repos as $i => $repo)
|
||||
{
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
if(!$this->checkPriv($repo)) unset($repos[$i]);
|
||||
}
|
||||
|
||||
return $repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repo pairs.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getRepoPairs()
|
||||
{
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq(0)->fetchAll();
|
||||
$repoPairs = array();
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
$scm = $repo->SCM == 'Subversion' ? 'svn' : 'git';
|
||||
if($this->checkPriv($repo)) $repoPairs[$repo->id] = "[{$scm}] " . $repo->name;
|
||||
}
|
||||
|
||||
return $repoPairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repo by id.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getRepoByID($repoID)
|
||||
{
|
||||
$repo = $this->dao->select('*')->from(TABLE_REPO)->where('id')->eq($repoID)->fetch();
|
||||
if(!$repo) return false;
|
||||
|
||||
if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password);
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
return $repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git branches.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBranches($repo)
|
||||
{
|
||||
$this->scm = $this->app->loadClass('scm');
|
||||
$this->scm->setEngine($repo);
|
||||
return $this->scm->branch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logs.
|
||||
*
|
||||
* @param object $repo
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @param string $type
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLogs($repo, $entry, $revision = 'HEAD', $type = 'dir', $pager = null)
|
||||
{
|
||||
$entry = ltrim($entry, '/');
|
||||
$entry = $repo->prefix . (empty($entry) ? '' : '/' . $entry);
|
||||
if((time() - strtotime($repo->lastSync)) / 60 >= $this->config->repo->syncTime) $this->updateLatestCommit($repo);
|
||||
|
||||
$repoID = $repo->id;
|
||||
$revisionTime = $this->dao->select('time')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($revision != 'HEAD')->andWhere('t1.revision')->eq($revision)->fi()
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->orderBy('time desc')
|
||||
->limit(1)
|
||||
->fetch('time');
|
||||
|
||||
$historyIdList = array();
|
||||
if($entry != '/' and !empty($entry))
|
||||
{
|
||||
$historyIdList = $this->dao->select('DISTINCT t2.id')->from(TABLE_REPOFILES)->alias('t1')
|
||||
->leftJoin(TABLE_REPOHISTORY)->alias('t2')->on('t1.revision=t2.id')
|
||||
->where('1=1')
|
||||
->andWhere('t1.repo')->eq($repo->id)
|
||||
->beginIF($type == 'dir')
|
||||
->andWhere('t1.parent', true)->like(rtrim($entry, '/') . "/%")
|
||||
->orWhere('t1.parent')->eq(rtrim($entry, '/'))
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->beginIF($type == 'file')->andWhere('t1.path')->eq("$entry")->fi()
|
||||
->orderBy('t2.`time` desc')
|
||||
->page($pager)
|
||||
->fetchPairs('id', 'id');
|
||||
}
|
||||
|
||||
$comments = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->andWhere('t1.`time`')->le($revisionTime)
|
||||
->andWhere('left(t1.comment, 12)')->ne('Merge branch')
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->beginIF($entry != '/' and !empty($entry))->andWhere('t1.id')->in($historyIdList)->fi()
|
||||
->orderBy('time desc');
|
||||
if($entry == '/' or empty($entry))$comments->page($pager, 't1.id');
|
||||
$comments = $comments->fetchAll('revision');
|
||||
|
||||
foreach($comments as $repoComment) $repoComment->comment = $this->replaceCommentLink($repoComment->comment);
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest comment.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getLatestComment($repoID)
|
||||
{
|
||||
$count = $this->dao->select('count(DISTINCT t1.id) as count')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->fetch('count');
|
||||
|
||||
$lastComment = $this->dao->select('t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->orderBy('t1.time desc')
|
||||
->limit(1)
|
||||
->fetch();
|
||||
if(empty($lastComment)) return null;
|
||||
|
||||
$repo = $this->getRepoByID($repoID);
|
||||
if($repo->SCM == 'Git' and $lastComment->commit != $count)
|
||||
{
|
||||
$this->fixCommit($repo->id);
|
||||
$lastComment->commit = $count;
|
||||
}
|
||||
|
||||
return $lastComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get revisions from db.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $limit
|
||||
* @param string $maxRevision
|
||||
* @param string $minRevision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getRevisionsFromDB($repoID, $limit = '', $maxRevision = '', $minRevision = '')
|
||||
{
|
||||
$revisions = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF(!empty($maxRevision))->andWhere('t1.revision')->le($maxRevision)->fi()
|
||||
->beginIF(!empty($minRevision))->andWhere('t1.revision')->ge($minRevision)->fi()
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->orderBy('t1.revision desc')
|
||||
->beginIF(!empty($limit))->limit($limit)->fi()
|
||||
->fetchAll('revision');
|
||||
$commiters = $this->loadModel('user')->getCommiters();
|
||||
foreach($revisions as $revision)
|
||||
{
|
||||
$revision->comment = $this->replaceCommentLink($revision->comment);
|
||||
$revision->committer = isset($commiters[$revision->committer]) ? $commiters[$revision->committer] : $revision->committer;
|
||||
}
|
||||
return $revisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get history.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param array $revisions
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getHistory($repoID, $revisions)
|
||||
{
|
||||
return $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->andWhere('t1.revision')->in($revisions)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->fetchAll('revision');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getReview($repoID, $entry, $revision)
|
||||
{
|
||||
$reviews = array();
|
||||
$bugs = $this->dao->select('t1.*, t2.realname')->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')
|
||||
->on('t1.openedBy = t2.account')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->andWhere('t1.entry')->eq($entry)
|
||||
->andWhere('t1.v2')->eq($revision)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->fetchAll('id');
|
||||
$comments = $this->dao->select('t1.*, t2.realname')->from(TABLE_ACTION)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')
|
||||
->on('t1.actor = t2.account')
|
||||
->where('t1.objectType')->eq('bug')
|
||||
->andWhere('t1.objectID')->in(array_keys($bugs))
|
||||
->andWhere('t1.action')->eq('commented')
|
||||
->fetchGroup('objectID', 'id');
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
if(common::hasPriv('bug', 'edit')) $bug->edit = true;
|
||||
if(common::hasPriv('bug', 'delete')) $bug->delete = true;
|
||||
$lines = explode(',', trim($bug->lines, ','));
|
||||
$line = $lines[0];
|
||||
$reviews[$line]['bugs'][$bug->id] = $bug;
|
||||
|
||||
if(isset($comments[$bug->id]))
|
||||
{
|
||||
foreach($comments[$bug->id] as $key => $comment)
|
||||
{
|
||||
if($comment->actor == $this->app->user->account) $comment->edit = true;
|
||||
}
|
||||
$reviews[$line]['comments'] = $comments;
|
||||
}
|
||||
}
|
||||
|
||||
return $reviews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git revisionName.
|
||||
*
|
||||
* @param string $revision
|
||||
* @param int $commit
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getGitRevisionName($revision, $commit)
|
||||
{
|
||||
if(empty($commit)) return substr($revision, 0, 10);
|
||||
return substr($revision, 0, 10) . '<span title="' . sprintf($this->lang->repo->commitTitle, $commit) . '"> (' . $commit . ') </span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* create
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->checkConnection();
|
||||
$data = fixer::input('post')->skipSpecial('path,client,account,password')->get();
|
||||
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
|
||||
if(empty($data->client)) $data->client = 'svn';
|
||||
|
||||
if($data->SCM == 'Subversion')
|
||||
{
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($data);
|
||||
$info = $scm->info('');
|
||||
$data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/');
|
||||
if($data->prefix) $data->prefix = '/' . $data->prefix;
|
||||
}
|
||||
|
||||
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
|
||||
$this->dao->insert(TABLE_REPO)->data($data)->exec();
|
||||
return $this->dao->lastInsertID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function saveSettings($repoID)
|
||||
{
|
||||
$this->checkConnection();
|
||||
$data = fixer::input('post')->skipSpecial('path,client,account,password')->get();
|
||||
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
|
||||
|
||||
if(empty($data->client)) $data->client = 'svn';
|
||||
$repo = $this->getRepoByID($repoID);
|
||||
$data->prefix = $repo->prefix;
|
||||
if($data->SCM == 'Subversion' and $data->path != $repo->path)
|
||||
{
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($data);
|
||||
$info = $scm->info('');
|
||||
$data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/');
|
||||
if($data->prefix) $data->prefix = '/' . $data->prefix;
|
||||
}
|
||||
elseif($data->SCM != $repo->SCM and $data->SCM == 'Git')
|
||||
{
|
||||
$data->prefix = '';
|
||||
}
|
||||
|
||||
if($data->path != $repo->path) $data->synced = 0;
|
||||
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
|
||||
$this->dao->update(TABLE_REPO)->data($data)->where('id')->eq($repoID)->exec();
|
||||
if($repo->path != $data->path)
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->exec();
|
||||
$this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($repoID)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save commit.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param array $logs
|
||||
* @param int $version
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function saveCommit($repoID, $logs, $version, $branch = '')
|
||||
{
|
||||
$count = 0;
|
||||
if(empty($logs)) return $count;
|
||||
|
||||
foreach($logs['commits'] as $i => $commit)
|
||||
{
|
||||
$existsRevision = $this->dao->select('id,revision')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('revision')->eq($commit->revision)->fetch();
|
||||
if($existsRevision)
|
||||
{
|
||||
if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($existsRevision->id)->set('branch')->eq($branch)->exec();
|
||||
continue;
|
||||
}
|
||||
|
||||
$commit->repo = $repoID;
|
||||
$commit->commit = $version;
|
||||
$commit->comment = htmlspecialchars($commit->comment);
|
||||
$this->dao->insert(TABLE_REPOHISTORY)->data($commit)->exec();
|
||||
if(!dao::isError())
|
||||
{
|
||||
$commitID = $this->dao->lastInsertID();
|
||||
if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($commitID)->set('branch')->eq($branch)->exec();
|
||||
foreach($logs['files'][$i] as $file)
|
||||
{
|
||||
$parentPath = dirname($file->path);
|
||||
|
||||
$file->parent = $parentPath == '\\' ? '/' : $parentPath;
|
||||
$file->revision = $commitID;
|
||||
$file->repo = $repoID;
|
||||
$this->dao->insert(TABLE_REPOFILES)->data($file)->exec();
|
||||
}
|
||||
$revisionPairs[$commit->revision] = $commit->revision;
|
||||
$version++;
|
||||
$count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dao::getError();
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save exists log branch.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveExistsLogBranch($repoID, $branch)
|
||||
{
|
||||
$lastBranchLog = $this->dao->select('t1.time')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->andWhere('t2.branch')->eq($branch)
|
||||
->orderBy('time')
|
||||
->limit(1)
|
||||
->fetch();
|
||||
$stmt = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('time')->lt($lastBranchLog->time)->query();
|
||||
while($log = $stmt->fetch())
|
||||
{
|
||||
$this->dao->REPLACE(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($log->id)->set('branch')->eq($branch)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update commit count.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updateCommitCount($repoID, $count)
|
||||
{
|
||||
return $this->dao->update(TABLE_REPO)->set('commits')->eq($count)->where('id')->eq($repoID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update latest commit.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updateLatestCommit($repo)
|
||||
{
|
||||
$repoID = $repo->id;
|
||||
$latestInDB = $this->getLatestComment($repoID);
|
||||
$version = empty($latestInDB) ? 1 : $latestInDB->commit + 1;
|
||||
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
$commitCount = $scm->getCommitCount(empty($latestInDB) ? 0 : $latestInDB->commit, empty($latestInDB) ? 0 : $latestInDB->revision);
|
||||
if($commitCount >= $version)
|
||||
{
|
||||
$revision = 'HEAD';
|
||||
$logs = $scm->getCommits($revision, $commitCount - $version + 1, $this->cookie->repoBranch);
|
||||
$logs['commits'] = array_reverse($logs['commits'], true);
|
||||
|
||||
$commitCount = $this->saveCommit($repoID, $logs, $version, $this->cookie->repoBranch);
|
||||
if($repo->SCM == 'Git' and empty($latestInDB)) $this->fixCommit($repo->id);
|
||||
$this->updateCommitCount($repoID, $commitCount);
|
||||
}
|
||||
$this->dao->update(TABLE_REPO)->set('lastSync')->eq(helper::now())->where('id')->eq($repoID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update comment.
|
||||
*
|
||||
* @param int $commentID
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function updateComment($commentID, $comment)
|
||||
{
|
||||
$this->dao->update(TABLE_ACTION)->set('comment')->eq($comment)->where('id')->eq($commentID)->exec();
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete comment.
|
||||
*
|
||||
* @param int $commentID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteComment($commentID)
|
||||
{
|
||||
return $this->dao->delete()->from(TABLE_ACTION)->where('id')->eq($commentID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pre and next revision.
|
||||
*
|
||||
* @param object $repo
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @param string $fileType
|
||||
* @param string $method
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getPreAndNext($repo, $entry, $revision = 'HEAD', $fileType = 'dir', $method = 'view')
|
||||
{
|
||||
$entry = ltrim($entry, '/');
|
||||
$entry = $repo->prefix . '/' . $entry;
|
||||
$repoID = $repo->id;
|
||||
|
||||
if($method == 'view')
|
||||
{
|
||||
$revisions = $this->dao->select('DISTINCT t1.revision,t1.commit')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOFILES)->alias('t2')->on('t1.id=t2.revision')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t3')->on('t1.id=t3.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t3.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->andWhere('t2.path')->eq("$entry")
|
||||
->orderBy('commit desc')
|
||||
->fetchPairs();
|
||||
}
|
||||
else
|
||||
{
|
||||
$revisions = $this->dao->select('DISTINCT t1.revision,t1.commit')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOFILES)->alias('t2')->on('t1.id=t2.revision')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t3')->on('t1.id=t3.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t3.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->beginIF($entry == '/')->andWhere('t2.revision = t1.id')->fi()
|
||||
->beginIF($fileType == 'dir' && $entry != '/')
|
||||
->andWhere('t2.parent', true)->like(rtrim($entry, '/') . "/%")
|
||||
->orWhere('t2.parent')->eq(rtrim($entry, '/'))
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->beginIF($fileType == 'file' && $entry != '/')->andWhere('t2.path')->eq($entry)->fi()
|
||||
->orderBy('commit desc')
|
||||
->fetchPairs();
|
||||
}
|
||||
|
||||
$preRevision = false;
|
||||
$preAndNext = new stdclass();
|
||||
$preAndNext->pre = '';
|
||||
$preAndNext->next = '';
|
||||
foreach($revisions as $version => $commit)
|
||||
{
|
||||
/* Get next object. */
|
||||
if($preRevision === true)
|
||||
{
|
||||
$preAndNext->next = $version;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get pre object. */
|
||||
if($revision == $version)
|
||||
{
|
||||
if($preRevision) $preAndNext->pre = $preRevision;
|
||||
$preRevision = true;
|
||||
}
|
||||
if($preRevision !== true) $preRevision = $version;
|
||||
}
|
||||
return $preAndNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create link for repo
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $params
|
||||
* @param string $pathParams
|
||||
* @param string $viewType
|
||||
* @param bool $onlybody
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createLink($method, $params = '', $pathParams = '', $viewType = '', $onlybody = false)
|
||||
{
|
||||
$link = helper::createLink('repo', $method, $params, $viewType, $onlybody);
|
||||
if(empty($pathParams)) return $link;
|
||||
|
||||
$link .= strpos($link, '?') === false ? '?' : '&';
|
||||
$link .= $pathParams;
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set back session/
|
||||
*
|
||||
* @param string $type
|
||||
* @param bool $withOtherModule
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setBackSession($type = 'list', $withOtherModule = false)
|
||||
{
|
||||
$backKey = 'repo' . ucfirst(strtolower($type));
|
||||
session_start();
|
||||
$uri = $this->app->getURI(true);
|
||||
if(!empty($_GET) and $this->config->requestType == 'PATH_INFO') $uri .= "?" . http_build_query($_GET);
|
||||
$_SESSION[$backKey] = $uri;
|
||||
if($type == 'list') unset($_SESSION['repoView']);
|
||||
if($withOtherModule)
|
||||
{
|
||||
$this->session->set('bugList', $uri);
|
||||
$this->session->set('taskList', $uri);
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set repo branch.
|
||||
*
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setRepoBranch($branch)
|
||||
{
|
||||
setcookie("repoBranch", $branch, 0, $this->config->webRoot);
|
||||
$_COOKIE['repoBranch'] = $branch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark synced status.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function markSynced($repoID)
|
||||
{
|
||||
$this->fixCommit($repoID);
|
||||
$this->dao->update(TABLE_REPO)->set('synced')->eq(1)->where('id')->eq($repoID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix commit.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function fixCommit($repoID)
|
||||
{
|
||||
$stmt = $this->dao->select('DISTINCT t1.id')->from(TABLE_REPOHISTORY)->alias('t1')
|
||||
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
|
||||
->orderBy('time')
|
||||
->query();
|
||||
|
||||
$i = 1;
|
||||
while($repoHistory = $stmt->fetch())
|
||||
{
|
||||
$this->dao->update(TABLE_REPOHISTORY)->set('`commit`')->eq($i)->where('id')->eq($repoHistory->id)->exec();
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode repo path.
|
||||
*
|
||||
* @param string $path
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function encodePath($path = '')
|
||||
{
|
||||
return helper::safe64Encode(urlencode($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode repo path.
|
||||
*
|
||||
* @param string $path
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function decodePath($path = '')
|
||||
{
|
||||
return trim(urldecode(helper::safe64Decode($path)), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check content is binary.
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $suffix
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function isBinary($content, $suffix = '')
|
||||
{
|
||||
if(strpos($this->config->repo->binary, "|$suffix|") !== false) return true;
|
||||
|
||||
$blk = substr($content, 0, 512);
|
||||
return (
|
||||
false ||
|
||||
substr_count($blk, "^\r\n")/512 > 0.3 ||
|
||||
substr_count($blk, "^ -~")/512 > 0.3 ||
|
||||
substr_count($blk, "\x00") > 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check connection
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkConnection()
|
||||
{
|
||||
if(empty($_POST)) return false;
|
||||
$scm = $this->post->SCM;
|
||||
$client = $this->post->client;
|
||||
$account = $this->post->account;
|
||||
$password = $this->post->password;
|
||||
$encoding = strtoupper($this->post->encoding);
|
||||
$path = $this->post->path;
|
||||
if($encoding != 'UTF8' and $encoding != 'UTF-8') $path = helper::convertEncoding($path, 'utf-8', $encoding);
|
||||
|
||||
if($scm == 'Subversion')
|
||||
{
|
||||
$path = '"' . $path . '"';
|
||||
if(stripos($path, 'https://') === 1 or stripos($path, 'svn://') === 1)
|
||||
{
|
||||
$ssh = true;
|
||||
$remote = true;
|
||||
$command = "$client info --username $account --password $password --non-interactive --trust-server-cert-failures=cn-mismatch --trust-server-cert --no-auth-cache $path 2>&1";
|
||||
}
|
||||
else if(stripos($path, 'file://') === 1)
|
||||
{
|
||||
$ssh = false;
|
||||
$remote = false;
|
||||
$command = "$client info --non-interactive --no-auth-cache $path 2>&1";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ssh = false;
|
||||
$remote = true;
|
||||
$command = "$client info --username $account --password $password --non-interactive --no-auth-cache $path 2>&1";
|
||||
}
|
||||
exec($command, $output, $result);
|
||||
if($result)
|
||||
{
|
||||
$versionCommand = "$client --version --quiet 2>&1";
|
||||
exec($versionCommand, $versionOutput, $versionResult);
|
||||
if($versionResult)
|
||||
{
|
||||
$message = sprintf($this->lang->repo->error->output, $versionCommand, $versionResult, join("\n", $versionOutput));
|
||||
echo $message;
|
||||
die(js::alert($this->lang->repo->error->cmd . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message)));
|
||||
}
|
||||
if($ssh and version_compare(end($versionOutput), '1.6', '<')) die(js::alert($this->lang->repo->error->version));
|
||||
$message = sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output));
|
||||
echo $message;
|
||||
if(stripos($message, 'Expected FS format between') !== false and strpos($message, 'found format') !== false) die(js::alert($this->lang->repo->error->clientVersion));
|
||||
if(preg_match('/[^\:\/\\A-Za-z0-9_\-\'\"]/', $path)) die(js::alert($this->lang->repo->error->encoding . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message)));
|
||||
die(js::alert($this->lang->repo->error->connect . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message)));
|
||||
}
|
||||
}
|
||||
elseif($scm == 'Git')
|
||||
{
|
||||
if(!chdir($path))
|
||||
{
|
||||
if(!is_dir($path)) die(js::alert(sprintf($this->lang->repo->error->noFile, $path)));
|
||||
if(!is_executable($path)) die(js::alert(sprintf($this->lang->repo->error->noPriv, $path)));
|
||||
die(js::alert($this->lang->repo->error->path));
|
||||
}
|
||||
|
||||
$command = "$client tag 2>&1";
|
||||
exec($command, $output, $result);
|
||||
if($result)
|
||||
{
|
||||
echo sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output));
|
||||
die(js::alert($this->lang->repo->error->connect));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace comment link.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function replaceCommentLink($comment)
|
||||
{
|
||||
$stories = array();
|
||||
$tasks = array();
|
||||
$bugs = array();
|
||||
$commonReg = "(?:\s){0,}((?:#|:|:){0,})([0-9, ]{1,})";
|
||||
$taskReg = '/task' . $commonReg . '/i';
|
||||
$storyReg = '/story' . $commonReg . '/i';
|
||||
$bugReg = '/bug' . $commonReg . '/i';
|
||||
if(preg_match_all($storyReg, $comment, $result))
|
||||
{
|
||||
$storyLinks = $this->addLink($result, 'story');
|
||||
foreach($storyLinks as $search => $replace) $comment = str_replace($search, $replace, $comment);
|
||||
}
|
||||
if(preg_match_all($taskReg, $comment, $result))
|
||||
{
|
||||
$taskLinks = $this->addLink($result, 'task');
|
||||
foreach($taskLinks as $search => $replace) $comment = str_replace($search, $replace, $comment);
|
||||
}
|
||||
if(preg_match_all($bugReg, $comment, $result))
|
||||
{
|
||||
$bugLinks = $this->addLink($result, 'bug');
|
||||
foreach($bugLinks as $search => $replace) $comment = str_replace($search, $replace, $comment);
|
||||
}
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add link.
|
||||
*
|
||||
* @param string $matches
|
||||
* @param string $method
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function addLink($matches, $method)
|
||||
{
|
||||
if(empty($matches)) return null;
|
||||
$replaceLines = array();
|
||||
foreach($matches[2] as $key => $ids)
|
||||
{
|
||||
$spit = strpos($ids, ',') !== false ? ',' : ' ';
|
||||
$ids = explode(' ', str_replace(',', ' ', $ids));
|
||||
$links = $method . " " . $matches[1][$key];
|
||||
foreach($ids as $id)
|
||||
{
|
||||
if($id) $links .= html::a(helper::createLink($method, 'view', "id=$id"), $id) . $spit;
|
||||
}
|
||||
$replaceLines[$matches[0][$key]] = rtrim($links, $spit);
|
||||
}
|
||||
return $replaceLines;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* The side logs view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2014 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
|
||||
* @license LGPL (http://www.gnu.org/licenses/lgpl.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package repo
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$pathInfo = '&root=' . $this->repo->encodePath(empty($path) ? '/' : $path);
|
||||
if(isset($entry)) $pathInfo .= '&type=file';
|
||||
?>
|
||||
<form id='logForm' class='main-table' data-ride='table' action='<?php echo $this->repo->createLink('diff', "repoID=$repoID", "entry=" . $this->repo->encodePath($path))?>' method='post'>
|
||||
<table class='table table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-40px'></th>
|
||||
<th class='w-80px'><?php echo $lang->repo->revisionA?></th>
|
||||
<?php if($repo->SCM == 'Git'):?>
|
||||
<th class='w-70px'><?php echo $lang->repo->commit?></th>
|
||||
<?php endif;?>
|
||||
<th class='w-80px'><?php echo $lang->repo->time?></th>
|
||||
<th class='w-100px'><?php echo $lang->repo->committer?></th>
|
||||
<th><?php echo $lang->repo->comment?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($revisions as $log):?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class='checkbox-primary'>
|
||||
<input type='checkbox' name='revision[]' value="<?php echo $log->revision?>" />
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
<td class='versions'><span class="revision"><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision={$log->revision}" . $pathInfo), $repo->SCM == 'Git' ? substr($log->revision, 0, 10) : $log->revision);?></span></td>
|
||||
<?php if($repo->SCM == 'Git'):?>
|
||||
<td><?php echo $log->commit?></td>
|
||||
<?php endif;?>
|
||||
<td><?php echo substr($log->time, 0, 10);?></td>
|
||||
<td><?php echo $log->committer;?></td>
|
||||
<?php $comment = htmlspecialchars($log->comment, ENT_QUOTES);?>
|
||||
<td title='<?php echo $comment?>' class='comment'><?php echo $log->comment?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class='table-footer'>
|
||||
<?php if(common::hasPriv('repo', 'diff')) echo html::submitButton($lang->repo->diff, '', count($revisions) < 2 ? 'disabled btn btn-primary' : 'btn btn-primary')?>
|
||||
<?php echo html::a($this->repo->createLink('log', "repoID=$repoID&entry=&revision=HEAD&type=$logType", "entry=" . $this->repo->encodePath($path)), $lang->repo->allLog);?>
|
||||
<div class='pull-right'>
|
||||
<div class='btn-group'>
|
||||
<?php
|
||||
$prePage = $pager->pageID == 1 ? 1 : $pager->pageID - 1;
|
||||
$nextPage = $pager->pageID == $pager->pageTotal ? $pager->pageID : $pager->pageID + 1;
|
||||
$params = "repoID=$repoID&path=&type=$logType&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";
|
||||
$preLink = $this->repo->createLink('ajaxSideLogs', "$params&pageID=$prePage", "path=" . $this->repo->encodePath($path));
|
||||
$nextLink = $this->repo->createLink('ajaxSideLogs', "$params&pageID=$nextPage", "path=" . $this->repo->encodePath($path));
|
||||
echo html::a($preLink, "<i class='icon icon-angle-left'></i>", '', "class='ajaxPager btn" . ($prePage == $pager->pageID ? ' disabled' : '') . "'");
|
||||
echo html::a($nextLink, "<i class='icon icon-angle-right'></i>", '', "class='ajaxPager btn" . ($nextPage == $pager->pageID ? ' disabled' : '') . "'");
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
if($("input:checkbox[name='revision[]']:checked").length < 2)
|
||||
{
|
||||
$("input:checkbox[name='revision[]']:lt(2)").attr('checked', 'checked');
|
||||
}
|
||||
$("input:checkbox[name='revision[]']").each(function(){ if(!$(this).is(':checked')) $(this).attr("disabled","disabled")});
|
||||
$("input:checkbox[name='revision[]']").click(function(){
|
||||
var checkNum = $("input:checkbox[name='revision[]']:checked").length;
|
||||
if (checkNum >= 2)
|
||||
{
|
||||
$("input:checkbox[name='revision[]']").each(function(){ if(!$(this).is(':checked')) $(this).attr("disabled","disabled")});
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#diffRepo').remove();
|
||||
$("input:checkbox[name='revision[]']").each(function(){$(this).attr("disabled", false)});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* The create view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: create.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php if(common::checkNotCN()):?>
|
||||
<style>
|
||||
.user-addon{padding-right: 16px; padding-left: 16px;}
|
||||
</style>
|
||||
<?php endif;?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->repo->create;?></h2>
|
||||
</div>
|
||||
<form class='form-indicator main-form' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->SCM;?></th>
|
||||
<td><?php echo html::select('SCM', $lang->repo->scmList, 'Subversion', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->name;?></th>
|
||||
<td><?php echo html::input('name', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->path;?></th>
|
||||
<td><?php echo html::input('path', '', "class='form-control'")?></td>
|
||||
<td class='muted'><?php echo $lang->repo->example->path;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->encoding;?></th>
|
||||
<td><?php echo html::input('encoding', 'utf-8', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->client;?></th>
|
||||
<td><?php echo html::input('client', '', "class='form-control'")?></td>
|
||||
<td class='muted'><?php echo $lang->repo->example->client;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->account;?></th>
|
||||
<td><?php echo html::input('account', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->password;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::password('password', '', "class='form-control'");?>
|
||||
<span class='input-group-addon fix-border fix-padding'></span>
|
||||
<?php echo html::select('encrypt', $lang->repo->encryptList, 'base64', "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->acl;?></th>
|
||||
<td class='acl'>
|
||||
<div class='input-group mgb-10'>
|
||||
<span class='input-group-addon'><?php echo $lang->repo->group?></span>
|
||||
<?php echo html::select('acl[groups][]', $groups, '', "class='form-control chosen' multiple")?>
|
||||
</div>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon user-addon'><?php echo $lang->repo->user?></span>
|
||||
<?php echo html::select('acl[users][]', $users, '', "class='form-control chosen' multiple")?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' class='text-center form-actions'>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* The diff view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: browse.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/form.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php
|
||||
$backURI = $this->session->repoView ? $this->session->repoView : $this->session->repoList;
|
||||
if($backURI)
|
||||
{
|
||||
echo html::a($backURI, "<i class='icon icon-back icon-sm'></i>" . $lang->goback, '', "class='btn btn-link'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::backButton("<i class='icon icon-back icon-sm'></i>" . $lang->goback, '', "btn btn-link");
|
||||
}
|
||||
?>
|
||||
<div class="divider"></div>
|
||||
<div class="page-title">
|
||||
<?php
|
||||
echo html::a($this->repo->createLink('browse', "repoID=$repoID"), $repo->name);
|
||||
$paths= explode('/', $entry);
|
||||
$fileName = array_pop($paths);
|
||||
$postPath = '';
|
||||
foreach($paths as $pathName)
|
||||
{
|
||||
$postPath .= $pathName . '/';
|
||||
echo '/' . ' ' . html::a($this->repo->createLink('browse', "repoID=$repoID", "path=" . $this->repo->encodePath($postPath)), trim($pathName, '/'));
|
||||
}
|
||||
echo '/' . ' ' . $fileName;
|
||||
if($repo->SCM == 'Git')
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? "$newRevision" : $oldRevision;
|
||||
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . $historys[$oldRevision] . ' : ' . $historys[$newRevision] . ')</span>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? $newRevision - 1 : $oldRevision;
|
||||
echo " <span class='label label-info'>$oldRevision : $newRevision</span>";
|
||||
}
|
||||
?>
|
||||
<span class='label label-exchange'><i class="icon icon-exchange"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="repo panel">
|
||||
<div class='panel-heading'>
|
||||
<form method='post'>
|
||||
<div class='btn-group pull-right'>
|
||||
<?php echo html::commonButton($lang->repo->viewDiffList['inline'], "id='inline'", $arrange == 'inline' ? 'active btn btn-sm' : 'btn btn-sm')?>
|
||||
<?php echo html::commonButton($lang->repo->viewDiffList['appose'], "id='appose'", $arrange == 'appose' ? 'active btn btn-sm' : 'btn btn-sm')?>
|
||||
</div>
|
||||
<div class='btn-toolbar'>
|
||||
<div class='btn-group'>
|
||||
<?php if(common::hasPriv('repo', 'download')) echo html::a($this->repo->createLink('download', "repoID=$repoID&path=&fromRevison=$oldRevision&toRevision=$newRevision&type=path", "path=" . $this->repo->encodePath($entry)), $lang->repo->downloadDiff, 'hiddenwin', "class='btn btn-sm btn-download'");?>
|
||||
<div class='btn-group'>
|
||||
<?php echo html::commonButton(zget($lang->repo->encodingList, $encoding, $lang->repo->encoding) . "<span class='caret'></span>", "data-toggle='dropdown'", 'btn dropdown-toggle btn-sm')?>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<?php foreach($lang->repo->encodingList as $key => $val):?>
|
||||
<li><?php echo html::a('javascript:changeEncoding("'. $key . '")', $val)?></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo html::hidden('arrange', $arrange) . html::hidden('encoding', $encoding) . html::hidden('revision[]', $newRevision) . html::hidden('revision[]', $oldRevision)?>
|
||||
</form>
|
||||
</div>
|
||||
<?php foreach($diffs as $diffFile):?>
|
||||
<div class='repoCode'>
|
||||
<table class='table diff' id='diff'>
|
||||
<caption><?php echo $diffFile->fileName;?></caption>
|
||||
<?php if(empty($diffFile->contents)) continue;?>
|
||||
<?php foreach($diffFile->contents as $content):?>
|
||||
<?php
|
||||
$oldCurrentLine = $content->oldStartLine;
|
||||
$newCurrentLine = $content->newStartLine;
|
||||
?>
|
||||
<?php if(!in_array($oldCurrentLine, array('0', '1')) and !in_array($newCurrentLine, array('0', '1'))):?>
|
||||
<tr data-line='<?php echo $newCurrentLine ?>' class='empty'>
|
||||
<th class='w-num text-center'>...</th>
|
||||
<?php if($arrange == 'appose'):?>
|
||||
<td class='none code'></td>
|
||||
<?php endif;?>
|
||||
<th class='w-num text-center'>...</th>
|
||||
<td class='none code'></td>
|
||||
</tr>
|
||||
<?php endif?>
|
||||
<?php if($arrange == 'inline'):?>
|
||||
<?php foreach($content->lines as $line):?>
|
||||
<tr data-line='<?php echo $line->newlc ?>'>
|
||||
<th class='w-num text-right'><?php if($line->type != 'new') echo $line->oldlc?></th>
|
||||
<th class='w-num text-left'><?php if($line->type != 'old') echo $line->newlc?></th>
|
||||
<td class='line-<?php echo $line->type?> code'><?php
|
||||
$line->line = $repo->SCM == 'Subversion' ? htmlspecialchars($line->line) : $line->line;
|
||||
echo $line->type == 'old' ? preg_replace('/^\-/', '–', $line->line) : ($line->type == 'new' ? $line->line : ' ' . $line->line);
|
||||
?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php else:?>
|
||||
<?php foreach($content->lines as $line):?>
|
||||
<tr data-line='<?php echo $line->newlc ?>'>
|
||||
<?php
|
||||
if($line->type == 'old')
|
||||
{
|
||||
$oldlc = $line->oldlc;
|
||||
$newlc = '';
|
||||
if(isset($content->new[$oldlc]))
|
||||
{
|
||||
$newlc = $line->oldlc;
|
||||
$line->type = 'custom';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oldlc = $line->oldlc;
|
||||
$newlc = $line->newlc;
|
||||
if(!isset($content->new[$newlc])) continue;
|
||||
}
|
||||
?>
|
||||
<th class='w-num text-right'><?php echo $oldlc?></th>
|
||||
<td class='w-code line-<?php if($line->type != 'new')echo $line->type?> <?php if($line->type == 'custom') echo "line-old"?> code'><?php
|
||||
if(!isset($content->old[$oldlc])) $content->old[$oldlc] = '';
|
||||
$content->old[$oldlc] = $repo->SCM == 'Subversion' ? htmlspecialchars($content->old[$oldlc]) : $content->old[$oldlc];
|
||||
if(!empty($oldlc)) echo $line->type != 'all' ? preg_replace('/^\-/', '–', $content->old[$oldlc]) : ' ' . $content->old[$oldlc];
|
||||
?></td>
|
||||
<th class='w-num text-right'><?php echo $newlc?></th>
|
||||
<td class='w-code line-<?php if($line->type != 'old') echo $line->type?> <?php if($line->type == 'custom') echo "line-new"?> code'><?php
|
||||
if(!isset($content->new[$newlc])) $content->new[$newlc] = '';
|
||||
$content->new[$newlc] = $repo->SCM == 'Subversion' ? htmlspecialchars($content->new[$newlc]) : $content->new[$newlc];
|
||||
if(!empty($newlc)) echo $line->type != 'all' ? $content->new[$newlc] : ' ' . $content->new[$newlc];
|
||||
?></td>
|
||||
<?php
|
||||
if(isset($content->old[$oldlc])) unset($content->old[$oldlc]);
|
||||
if(isset($content->new[$newlc])) unset($content->new[$newlc]);
|
||||
?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach?>
|
||||
</div>
|
||||
<div class='revisions hidden'>
|
||||
<?php
|
||||
if($repo->SCM == 'Git')
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? "$newRevision" : $oldRevision;
|
||||
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . $historys[$oldRevision] . ' : ' . $historys[$newRevision] . ')</span>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? $newRevision - 1 : $oldRevision;
|
||||
echo " <span class='label label-info'>$oldRevision : $newRevision</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<form method="post" id="exchange" class="hidden">
|
||||
<input type="hidden" name="revision[]" value="<?php echo $oldRevision;?>"/>
|
||||
<input type="hidden" name="revision[]" value="<?php echo $newRevision;?>"/>
|
||||
</form>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* The log view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: log.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class="btn-toolbar pull-left">
|
||||
<div class="page-title">
|
||||
<strong>
|
||||
<?php
|
||||
echo html::a($this->repo->createLink('log', "repoID=$repoID"), $repo->name);
|
||||
$paths= explode('/', $entry);
|
||||
$fileName = array_pop($paths);
|
||||
$postPath = '';
|
||||
foreach($paths as $pathName)
|
||||
{
|
||||
$postPath .= $pathName . '/';
|
||||
echo '/' . ' ' . html::a($this->repo->createLink('log', "repoID=$repoID", "entry=" . $this->repo->encodePath($postPath)), trim($pathName, '/'));
|
||||
}
|
||||
echo '/' . ' ' . $fileName;
|
||||
echo $repo->SCM == 'Git' ? " @ " . substr($revision, 0, 10) : " @ r" . $revision;;
|
||||
?>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mainContent">
|
||||
<nav id="contentNav">
|
||||
<ul class="nav nav-default">
|
||||
<?php $encodeEntry = $this->repo->encodePath($entry);?>
|
||||
<li><a><?php echo $lang->repo->log;?></a></li>
|
||||
<?php if($info->kind == 'file') echo '<li>' . html::a($this->repo->createLink('download', "repoID=$repoID&path=&fromRevision=$revision", "path=$encodeEntry"), $lang->repo->download, 'hiddenwin') . '</li>';?>
|
||||
</ul>
|
||||
</nav>
|
||||
<form id='logForm' class='main-table' data-ride='table' action='<?php echo $this->repo->createLink('diff', "repoID=$repoID", "entry=" . $this->repo->encodePath($entry))?>' method='post'>
|
||||
<table class='table table-fixed' id='logList'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-40px'></th>
|
||||
<th width='w-110px'><?php echo $lang->repo->revision?></th>
|
||||
<th width='w-150px'><?php echo $lang->repo->date?></th>
|
||||
<th width='w-80px'><?php echo $lang->repo->committer?></th>
|
||||
<th><?php echo $lang->repo->comment?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($logs as $log):?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class='checkbox-primary'>
|
||||
<input type='checkbox' name='revision[]' value="<?php echo $log->revision?>" />
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
<td class='versions'><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision=" . $log->revision), substr($log->revision, 0, 10));?></td>
|
||||
<td><?php echo $log->time;?></td>
|
||||
<td><?php echo $log->committer;?></td>
|
||||
<td class='comment'><?php echo $log->comment;?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class='table-footer'>
|
||||
<?php echo html::submitButton($lang->repo->diff, '', 'btn btn-primary')?>
|
||||
<?php $pager->show('right', 'pagerjs');?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* The revision view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: revision.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
session_start();
|
||||
$_SESSION['repoList'] = $this->app->getURI(true);
|
||||
session_write_close();
|
||||
$pathInfo = empty($path) ? '' : '&root=' . $this->repo->encodePath($path);
|
||||
$preDir = empty($parentDir) ? $pathInfo : '&path=' . $this->repo->encodePath($parentDir);
|
||||
$typeInfo = $type == 'file' ? '&type=file' : '';
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php echo html::a($this->repo->createLink('browse', "repoID=$repoID" . $preDir), "<i class='icon icon-back'></i>" . $lang->goback, '', "class='btn btn-link'");?>
|
||||
<div class="divider"></div>
|
||||
<div class="page-title">
|
||||
<?php echo $lang->repo->revisionA . ' ' . ($repo->SCM == 'Git' ? $this->repo->getGitRevisionName($revision, $log->commit) : $revision);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col col-8'>
|
||||
<div class='cell'>
|
||||
<div class='detail'>
|
||||
<div class='detail-title'>
|
||||
<?php echo $lang->repo->changes;?>
|
||||
<div class='pull-right'><?php if(common::hasPriv('repo', 'diff')) echo html::a($this->repo->createLink('diff', "repoID=$repoID&entry=&fromRevision=$oldRevision&toRevision=$revision"), $lang->repo->diffAll);?></div>
|
||||
</div>
|
||||
<div class='detail-content'>
|
||||
<table class='table no-margin'>
|
||||
<?php foreach($changes as $path => $change):?>
|
||||
<tr>
|
||||
<td><?php echo "<span class='label label-info label-badge'>" . $change['action'] . '</span> ' . $path?></td>
|
||||
<td class='w-80px text-center'><?php echo zget($change, 'view', '') . zget($change, 'diff', '')?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='side-col col-4'>
|
||||
<div class='cell'>
|
||||
<div class='detail'>
|
||||
<div class='detail-title'><?php echo $lang->repo->info?></div>
|
||||
<div class='detail-content'>
|
||||
<table class='table table-data'>
|
||||
<tr>
|
||||
<th class='w-80px'><?php echo $lang->repo->committer?></th>
|
||||
<td><?php echo $log->committer?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->revisionA?></th>
|
||||
<td><?php echo $log->revision?></td>
|
||||
</tr>
|
||||
<?php if($repo->SCM == 'Git'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->commit?></th>
|
||||
<td><?php echo $log->commit?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->comment?></th>
|
||||
<td><?php echo $log->comment?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->time?></th>
|
||||
<td><?php echo $log->time?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mainActions" class='main-actions'>
|
||||
<nav class="container">
|
||||
<?php if(!empty($preAndNext->pre)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision={$preAndNext->pre}" . $pathInfo . $typeInfo, "", 'html'), "<i class='icon-pre icon-chevron-left'></i>", '', "id='prevPage' class='btn btn-info' title='{$preAndNext->pre}'")?>
|
||||
<?php if(!empty($preAndNext->next)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision={$preAndNext->next}" . $pathInfo . $typeInfo, "", 'html'), "<i class='icon-pre icon-chevron-right'></i>", '', "id='nextPage' class='btn btn-info' title='{$preAndNext->next}'")?>
|
||||
</nav>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* The settings view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: setting.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php if(common::checkNotCN()):?>
|
||||
<style>
|
||||
.user-addon{padding-right: 16px; padding-left: 16px;}
|
||||
</style>
|
||||
<?php endif;?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->repo->settings;?></h2>
|
||||
</div>
|
||||
<form class='form-indicator main-form' method='post' target='hiddenwin'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->SCM;?></th>
|
||||
<td><?php echo html::select('SCM', $lang->repo->scmList, $repo->SCM, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->name;?></th>
|
||||
<td><?php echo html::input('name', $repo->name, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->path;?></th>
|
||||
<td><?php echo html::input('path', $repo->path, "class='form-control'")?></td>
|
||||
<td class='text-muted'><?php echo $lang->repo->example->path;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->encoding;?></th>
|
||||
<td><?php echo html::input('encoding', $repo->encoding, "class='form-control'")?></td>
|
||||
<td class='text-muted'><?php echo $lang->repo->example->encoding;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->client;?></th>
|
||||
<td><?php echo html::input('client', $repo->client, "class='form-control'")?></td>
|
||||
<td class='text-muted'><?php echo $lang->repo->example->client;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->account;?></th>
|
||||
<td>
|
||||
<?php echo html::input('account', $repo->account, "class='form-control' autocomplete='off'");?>
|
||||
<input type='text' style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->password;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::password('password', $repo->password, "class='form-control'");?>
|
||||
<span class='input-group-addon fix-border fix-padding'></span>
|
||||
<?php echo html::select('encrypt', $lang->repo->encryptList, $repo->encrypt, "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->acl;?></th>
|
||||
<td>
|
||||
<div class='input-group mgb-10'>
|
||||
<span class='input-group-addon'><?php echo $lang->repo->group?></span>
|
||||
<?php echo html::select('acl[groups][]', $groups, empty($repo->acl->groups) ? '' : join(',', $repo->acl->groups), "class='form-control chosen' multiple")?>
|
||||
</div>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon user-addon'><?php echo $lang->repo->user?></span>
|
||||
<?php echo html::select('acl[users][]', $users, empty($repo->acl->users) ? '' : join(',', $repo->acl->users), "class='form-control chosen' multiple")?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' class='text-center form-actions'>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* The showSyncComment view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
|
||||
* @license LGPL (http://www.gnu.org/licenses/lgpl.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package repo
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="mainContent" class="main-content">
|
||||
<div class='cell'>
|
||||
<div class='alert with-icon'>
|
||||
<i class="icon-check-sign"></i>
|
||||
<div class='content'>
|
||||
<h3><?php echo $lang->repo->notice->syncing;?></h3>
|
||||
<hr>
|
||||
<p><?php echo $lang->repo->notice->syncedCount?><span id='commits'><?php echo $version?></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script language='Javascript'>
|
||||
$(function(){
|
||||
var link = createLink('repo', 'ajaxSyncComment', "repoID=<?php echo $repoID?>");
|
||||
function syncComments()
|
||||
{
|
||||
$.get(link, function(data)
|
||||
{
|
||||
if(data == 'finish')
|
||||
{
|
||||
$('#caption').text('<?php echo $lang->repo->notice->syncComplete?>');
|
||||
return self.location = createLink('repo', 'log', "repoID=<?php echo $repoID?>");
|
||||
}
|
||||
$('#commits').html(parseInt($('#commits').html()) + parseInt(data));
|
||||
setTimeout(syncComments, 10);
|
||||
});
|
||||
}
|
||||
setTimeout(syncComments, 500);
|
||||
})
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* The create view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package repo
|
||||
* @version $Id: create.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
include '../../common/view/header.html.php';
|
||||
include '../../common/view/form.html.php';
|
||||
include '../../common/view/kindeditor.html.php';
|
||||
js::import($jsRoot . 'misc/highlight/highlight.pack.js');
|
||||
css::import($jsRoot . 'misc/highlight/styles/github.css');
|
||||
$encodePath = $this->repo->encodePath($entry);
|
||||
$version = " <span class=\"label label-info\">$revisionName</span>";
|
||||
?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php echo html::a($this->session->repoList, "<i class='icon icon-back icon-sm'></i>" . $lang->goback, '', "class='btn btn-link'");?>
|
||||
<div class="divider"></div>
|
||||
<div class="page-title">
|
||||
<strong>
|
||||
<?php
|
||||
echo html::a($this->repo->createLink('browse', "repoID=$repoID"), $repo->name);
|
||||
$paths= explode('/', $entry);
|
||||
$fileName = array_pop($paths);
|
||||
$postPath = '';
|
||||
foreach($paths as $pathName)
|
||||
{
|
||||
$postPath .= $pathName . '/';
|
||||
echo '/' . ' ' . html::a($this->repo->createLink('browse', "repoID=$repoID", "path=" . $this->repo->encodePath($postPath)), trim($pathName, '/'));
|
||||
}
|
||||
echo '/' . ' ' . $fileName;
|
||||
echo $version;
|
||||
?>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision=$revision"), $lang->repo->allChanges, '', "class='btn btn-primary'")?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id="mainContent" class="main-row fade">
|
||||
<?php endif;?>
|
||||
<div class="main-col repoCode main">
|
||||
<div class="content panel">
|
||||
<div class='panel-heading'>
|
||||
<div class='panel-title'><?php echo $entry?></div>
|
||||
<div class='panel-actions'>
|
||||
<?php if($suffix != 'binary' and strpos($config->repo->images, "|$suffix|") === false):?>
|
||||
<?php
|
||||
if(common::hasPriv('repo', 'download')) echo html::a($this->repo->createLink('download', "repoID=$repoID&path=&fromRevision=$revision", "path=$encodePath"), html::icon('download-alt') . $lang->repo->download, 'hiddenwin', "class='btn btn-sm btn-primary'");
|
||||
?>
|
||||
<?php endif;?>
|
||||
<div class='btn-group'>
|
||||
<?php echo html::commonButton(zget($lang->repo->encodingList, $encoding, $lang->repo->encoding) . "<span class='caret'></span>", "id='encoding' data-toggle='dropdown'", 'btn btn-sm btn-primary dropdown-toggle')?>
|
||||
<ul class='dropdown-menu' role='menu' aria-labelledby='encoding'>
|
||||
<?php foreach($lang->repo->encodingList as $key => $val):?>
|
||||
<li><?php echo html::a($this->repo->createLink('view', "repoID=$repoID&entry=&revision=$revision&showBug=$showBug&encoding=$key", "entry=$encodePath", 'html', isonlybody()), $val)?></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if(strpos($config->repo->images, "|$suffix|") !== false):?>
|
||||
<div class='image'><img src='data:image/<?php echo $suffix?>;base64,<?php echo $content?>' /></div>
|
||||
<?php elseif($suffix == 'binary'):?>
|
||||
<div class='binary'><?php echo html::a($this->repo->createLink('download', "repoID=$repoID&path=&fromRevision=$revision", "path=" . $this->repo->encodePath($entry)), "<i class='icon-download'></i>", 'hiddenwin', "title='{$lang->repo->download}'"); ?></div>
|
||||
<?php else:?>
|
||||
<pre class="<?php echo $config->program->suffix[$suffix];?>"><?php echo trim(htmlspecialchars($content, defined('ENT_SUBSTITUTE') ? ENT_QUOTES | ENT_SUBSTITUTE : ENT_QUOTES));?></pre>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div class="side-col" id="sidebar">
|
||||
<div class="sidebar-toggle"><i class="icon icon-angle-right"></i></div>
|
||||
<div class='side-body'><?php include 'ajaxsidelogs.html.php';?></div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php if(!isonlybody()):?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id="mainActions" class='main-actions'>
|
||||
<nav class="container">
|
||||
<?php if(!empty($preAndNext->pre)) echo html::a($this->repo->createLink('view', "repoID=$repoID&entry=&revision={$preAndNext->pre}&showBug=$showBug", "entry=$encodePath", 'html', isonlybody()), "<i class='icon-pre icon-chevron-left'></i>", '', "id='prevPage' class='btn btn-info' title='{$preAndNext->pre}'")?>
|
||||
<?php if(!empty($preAndNext->next)) echo html::a($this->repo->createLink('view', "repoID=$repoID&entry=&revision={$preAndNext->next}&showBug=$showBug", "entry=$encodePath", 'html', isonlybody()), "<i class='icon-pre icon-chevron-right'></i>", '', "id='nextPage' class='btn btn-info' title='{$preAndNext->next}'")?>
|
||||
</nav>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
<!-- saved from url=(0013)about:internet -->
|
||||
<!-- ^^^ This is for IE not to show security warning for local files,
|
||||
see http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx-->
|
||||
|
||||
<!--
|
||||
Highlighted code export
|
||||
Copyright (c) Vladimir Gubarkov <xonixx@gmail.com>
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Highlited code export</title>
|
||||
<link rel="stylesheet" href="styles/default.css">
|
||||
<meta charset="utf-8">
|
||||
<style type="text/css">
|
||||
#t1, #t2 { width: 100%;}
|
||||
tr { vertical-align: top; }
|
||||
address { margin-top: 4em; }
|
||||
</style>
|
||||
<script src="highlight.pack.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
String.prototype.escape = function() {
|
||||
return this.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
|
||||
}
|
||||
|
||||
function doIt() {
|
||||
var viewDiv = document.getElementById("highlight-view");
|
||||
var t1 = document.getElementById("t1");
|
||||
var t2 = document.getElementById("t2");
|
||||
var selector = document.getElementById("langSelector");
|
||||
var selectedLang = selector.options[selector.selectedIndex].value.toLowerCase();
|
||||
if(selectedLang) {
|
||||
viewDiv.innerHTML = '<pre><code class="'+selectedLang+'">'+t1.value.escape()+"</code></pre>";
|
||||
} else { // try auto
|
||||
viewDiv.innerHTML = '<pre><code>' + t1.value.escape() + "</code></pre>";
|
||||
}
|
||||
hljs.highlightBlock(viewDiv.firstChild.firstChild);
|
||||
t2.value = viewDiv.innerHTML;
|
||||
}
|
||||
|
||||
function copyToBuffer(textToCopy) {
|
||||
if (window.clipboardData) { // IE
|
||||
window.clipboardData.setData("Text", textToCopy);
|
||||
} else if (window.netscape) { // FF
|
||||
// from http://developer.mozilla.org/en/docs/Using_the_Clipboard
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
|
||||
gClipboardHelper.copyString(textToCopy);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var langSelectorHtml = '<label>Language <select id="langSelector">';
|
||||
langSelectorHtml += '<option value="">Auto</option>';
|
||||
for (var i in hljs.LANGUAGES) {
|
||||
if (hljs.LANGUAGES.hasOwnProperty(i))
|
||||
langSelectorHtml += '<option value=\"'+i+'\">'+i.charAt(0).toUpperCase()+i.substr(1)+'</option>';
|
||||
}
|
||||
langSelectorHtml += '</select></label>';
|
||||
document.write(langSelectorHtml);
|
||||
</script>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td><textarea rows="20" cols="50" id="t1"></textarea></td>
|
||||
<td><textarea rows="20" cols="50" id="t2"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Write a code snippet</td>
|
||||
<td>Get HTML to paste anywhere (for actual styles and colors see sample.css)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table width="98%">
|
||||
<tr>
|
||||
<td><input type="button" value="Export →" onclick="doIt()"/></td>
|
||||
<td align="right"><input type="button" value="Copy to buffer" onclick="copyToBuffer(document.getElementById('t2').value);"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="highlight-view"></div>
|
||||
<address>
|
||||
Export script: <a href="mailto:xonixx@gmail.com">Vladimir Gubarkov</a><br>
|
||||
Highlighting: <a href="http://softwaremaniacs.org/soft/highlight/">highlight.js</a>
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.diff .hljs-header,
|
||||
.hljs-javadoc {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.css .rule .hljs-keyword,
|
||||
.hljs-winutils,
|
||||
.nginx .hljs-title,
|
||||
.hljs-subst,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-hexcolor,
|
||||
.ruby .hljs-constant {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-phpdoc,
|
||||
.hljs-dartdoc,
|
||||
.tex .hljs-formula {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-id,
|
||||
.scss .hljs-preprocessor {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-list .hljs-keyword,
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-type,
|
||||
.vhdl .hljs-literal,
|
||||
.tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-title,
|
||||
.hljs-rules .hljs-property,
|
||||
.django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-attribute,
|
||||
.hljs-variable,
|
||||
.lisp .hljs-body {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-regexp {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.lisp .hljs-keyword,
|
||||
.clojure .hljs-keyword,
|
||||
.scheme .hljs-keyword,
|
||||
.tex .hljs-special,
|
||||
.hljs-prompt {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-pragma,
|
||||
.hljs-pi,
|
||||
.hljs-doctype,
|
||||
.hljs-shebang,
|
||||
.hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.diff .hljs-change {
|
||||
background: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-chunk {
|
||||
color: #aaa;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
|
||||
Google Code style (c) Aahan Krish <geekpanth3r@gmail.com>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: white;
|
||||
color: black;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-javadoc {
|
||||
color: #800;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.method,
|
||||
.hljs-list .hljs-keyword,
|
||||
.nginx .hljs-title,
|
||||
.hljs-tag .hljs-title,
|
||||
.setting .hljs-value,
|
||||
.hljs-winutils,
|
||||
.tex .hljs-command,
|
||||
.http .hljs-title,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: #008;
|
||||
}
|
||||
|
||||
.hljs-envvar,
|
||||
.tex .hljs-special {
|
||||
color: #660;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-cdata,
|
||||
.hljs-filter .hljs-argument,
|
||||
.hljs-attr_selector,
|
||||
.apache .hljs-cbracket,
|
||||
.hljs-date,
|
||||
.hljs-regexp,
|
||||
.coffeescript .hljs-attribute {
|
||||
color: #080;
|
||||
}
|
||||
|
||||
.hljs-sub .hljs-identifier,
|
||||
.hljs-pi,
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-keyword,
|
||||
.hljs-decorator,
|
||||
.ini .hljs-title,
|
||||
.hljs-shebang,
|
||||
.hljs-prompt,
|
||||
.hljs-hexcolor,
|
||||
.hljs-rules .hljs-value,
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.hljs-number,
|
||||
.css .hljs-function,
|
||||
.clojure .hljs-attribute {
|
||||
color: #066;
|
||||
}
|
||||
|
||||
.hljs-class .hljs-title,
|
||||
.smalltalk .hljs-class,
|
||||
.hljs-javadoctag,
|
||||
.hljs-yardoctag,
|
||||
.hljs-phpdoc,
|
||||
.hljs-dartdoc,
|
||||
.hljs-type,
|
||||
.hljs-typename,
|
||||
.hljs-tag .hljs-attribute,
|
||||
.hljs-doctype,
|
||||
.hljs-class .hljs-id,
|
||||
.hljs-built_in,
|
||||
.setting,
|
||||
.hljs-params,
|
||||
.hljs-variable {
|
||||
color: #606;
|
||||
}
|
||||
|
||||
.css .hljs-tag,
|
||||
.hljs-rules .hljs-property,
|
||||
.hljs-pseudo,
|
||||
.hljs-subst {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.css .hljs-class,
|
||||
.css .hljs-id {
|
||||
color: #9b703f;
|
||||
}
|
||||
|
||||
.hljs-value .hljs-important {
|
||||
color: #ff7700;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-rules .hljs-keyword {
|
||||
color: #c5af75;
|
||||
}
|
||||
|
||||
.hljs-annotation,
|
||||
.apache .hljs-sqbracket,
|
||||
.nginx .hljs-built_in {
|
||||
color: #9b859d;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-preprocessor *,
|
||||
.hljs-pragma {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.tex .hljs-formula {
|
||||
background-color: #eee;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.diff .hljs-header,
|
||||
.hljs-chunk {
|
||||
color: #808080;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.diff .hljs-change {
|
||||
background-color: #bccff9;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #baeeba;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #ffc8bd;
|
||||
}
|
||||
|
||||
.hljs-comment .hljs-yardoctag {
|
||||
font-weight: bold;
|
||||
}
|
||||
Reference in New Issue
Block a user