Merge branch 'master' into zentaopms_12.0.1
This commit is contained in:
@@ -69,6 +69,7 @@ zentaoxx:
|
||||
cp -r xuan/xxb/module/common/view/marked.html.php zentaoxx/module/common/view
|
||||
cp -r xuan/xxb/module/common/view/footer.modal.html.php zentaoxx/module/common/view
|
||||
cp -r xuan/xxb/module/common/view/version.html.php zentaoxx/module/common/view
|
||||
cp -r xuan/xxb/module/license zentaoxx/module/
|
||||
mkdir -p zentaoxx/www/js/
|
||||
cp -r xuan/xxb/www/js/markedjs zentaoxx/www/js/
|
||||
cp -r xuan/xxb/www/js/version.js zentaoxx/www/js/
|
||||
|
||||
+3
-3
@@ -141,7 +141,7 @@ echo $deletelog > $basePath/deletelog.sh
|
||||
echo "deletelog.sh ok"
|
||||
|
||||
# cron
|
||||
if [ ! -d "$basePath/cron" ]; then
|
||||
if [ ! -d "$basePath/cron" ]; then
|
||||
mkdir $basePath/cron
|
||||
fi
|
||||
echo "# system cron." > $basePath/cron/sys.cron
|
||||
@@ -149,8 +149,8 @@ echo "#min hour day month week command." >> $basePath/cron/sys.cron
|
||||
echo "0 1 * * * $basePath/dailyreminder.sh # dailyreminder." >> $basePath/cron/sys.cron
|
||||
echo "1 1 * * * $basePath/backup.sh # backup database and file." >> $basePath/cron/sys.cron
|
||||
echo "1 23 * * * $basePath/computeburn.sh # compute burndown chart." >> $basePath/cron/sys.cron
|
||||
echo "1-59/2 * * * * $basePath/syncsvn.sh # sync subversion." >> $basePath/cron/sys.cron
|
||||
echo "1-59/2 * * * * $basePath/syncgit.sh # sync git." >> $basePath/cron/sys.cron
|
||||
echo "1-59/5 * * * * $basePath/syncsvn.sh # sync subversion." >> $basePath/cron/sys.cron
|
||||
echo "1-59/5 * * * * $basePath/syncgit.sh # sync git." >> $basePath/cron/sys.cron
|
||||
echo "1-59/5 * * * * $basePath/sendmail.sh # async send mail." >> $basePath/cron/sys.cron
|
||||
echo "1-59/5 * * * * $basePath/sendwebhook.sh # async send webhook." >> $basePath/cron/sys.cron
|
||||
echo "1 1 * * * $basePath/createcycle.sh # create cycle todo." >> $basePath/cron/sys.cron
|
||||
|
||||
@@ -163,12 +163,15 @@ 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_JENKINS', '`' . $config->db->prefix . 'jenkins`');
|
||||
define('TABLE_INTEGRATION', '`' . $config->db->prefix . 'integration`');
|
||||
define('TABLE_COMPILE', '`' . $config->db->prefix . 'compile`');
|
||||
|
||||
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
|
||||
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS `zt_repofiles` (
|
||||
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` CHANGE `caseVersion` `caseVersion` smallint(6) NOT NULL DEFAULT 1 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`;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
CREATE TABLE `zt_jenkins` (
|
||||
`id` smallint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`url` varchar(255) DEFAULT NULL,
|
||||
`account` varchar(30) DEFAULT NULL,
|
||||
`password` varchar(30) NOT NULL,
|
||||
`encrypt` varchar(30) NOT NULL DEFAULT 'plain',
|
||||
`token` varchar(255) DEFAULT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_cijob` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`jenkins` mediumint(8) unsigned NOT NULL,
|
||||
`jenkinsJob` varchar(500) NOT NULL,
|
||||
`triggerType` varchar(255) NOT NULL,
|
||||
`scheduleType` varchar(255) NOT NULL,
|
||||
`cronExpression` varchar(255) DEFAULT NULL,
|
||||
`scheduleDay` varchar(255) DEFAULT NULL,
|
||||
`scheduleTime` varchar(255) DEFAULT NULL,
|
||||
`scheduleInterval` mediumint(8) DEFAULT NULL,
|
||||
`tagKeywords` varchar(255) DEFAULT NULL,
|
||||
`commentKeywords` varchar(255) DEFAULT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`lastExec` datetime DEFAULT NULL,
|
||||
`lastStatus` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_cibuild` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`cijob` mediumint(8) unsigned NOT NULL,
|
||||
`queueItem` mediumint(8) NOT NULL,
|
||||
`status` varchar(255) NOT NULL,
|
||||
`logs` text,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`updateDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `zt_cijob` ADD `svnFolder` varchar(255) COLLATE 'utf8_general_ci' NOT NULL AFTER `triggerType`;
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
|
||||
('1', '1', '*', '*', '*', 'moduleName=ci&methodName=buildTodayJob', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkBuildStatus', '同步Jenkins任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行Jenkins任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
|
||||
ALTER TABLE `zt_cibuild` RENAME TO `zt_compile`;
|
||||
ALTER TABLE `zt_cijob` RENAME TO `zt_integration`;
|
||||
|
||||
ALTER TABLE `zt_integration`
|
||||
DROP `scheduleType`,
|
||||
DROP `cronExpression`,
|
||||
DROP `scheduleTime`,
|
||||
DROP `scheduleInterval`;
|
||||
+117
-2
@@ -89,7 +89,7 @@ CREATE TABLE IF NOT EXISTS `zt_bug` (
|
||||
`duplicateBug` mediumint(8) unsigned NOT NULL,
|
||||
`linkBug` varchar(255) NOT NULL,
|
||||
`case` mediumint(8) unsigned NOT NULL,
|
||||
`caseVersion` smallint(6) NOT NULL default '1',
|
||||
`caseVersion` smallint(6) NOT NULL DEFAULT '1',
|
||||
`result` mediumint(8) unsigned NOT NULL,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`entry` varchar(255) NOT NULL,
|
||||
@@ -1045,6 +1045,118 @@ CREATE TABLE `zt_score` (
|
||||
KEY `method` (`method`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- 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,
|
||||
`desc` TEXT 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`,`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`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_jenkins` (
|
||||
`id` smallint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`url` varchar(255) DEFAULT NULL,
|
||||
`account` varchar(30) DEFAULT NULL,
|
||||
`password` varchar(30) NOT NULL,
|
||||
`encrypt` varchar(30) NOT NULL DEFAULT 'plain',
|
||||
`token` varchar(255) DEFAULT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_integration` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`jenkins` mediumint(8) unsigned NOT NULL,
|
||||
`jenkinsJob` varchar(500) NOT NULL,
|
||||
`triggerType` varchar(255) NOT NULL,
|
||||
`svnFolder` varchar(255) NOT NULL,
|
||||
`scheduleType` varchar(255) NOT NULL,
|
||||
`cronExpression` varchar(255) DEFAULT NULL,
|
||||
`scheduleDay` varchar(255) DEFAULT NULL,
|
||||
`scheduleTime` varchar(255) DEFAULT NULL,
|
||||
`scheduleInterval` mediumint(8) DEFAULT NULL,
|
||||
`tagKeywords` varchar(255) DEFAULT NULL,
|
||||
`commentKeywords` varchar(255) DEFAULT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`lastExec` datetime DEFAULT NULL,
|
||||
`lastStatus` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_compile` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`cijob` mediumint(8) unsigned NOT NULL,
|
||||
`queueItem` mediumint(8) NOT NULL,
|
||||
`status` varchar(255) NOT NULL,
|
||||
`logs` text,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`updateDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
|
||||
('*', '*', '*', '*', '*', '', '监控定时任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('30', '23', '*', '*', '*', 'moduleName=project&methodName=computeburn', '更新燃尽图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
@@ -1055,7 +1167,10 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=mail&methodName=asyncSend', '异步发信', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=webhook&methodName=asyncSend', '异步发送Webhook', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=admin&methodName=deleteLog', '删除过期日志', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('1', '1', '*', '*', '*', 'moduleName=ci&methodName=buildTodayJob', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkBuildStatus', '同步Jenkins任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行Jenkins任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
|
||||
INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
|
||||
(1, 'ADMIN', 'admin', 'for administrator'),
|
||||
|
||||
+6
-6
@@ -2,19 +2,19 @@ Z PUBLIC LICENSE 1.2
|
||||
|
||||
Authorization
|
||||
|
||||
Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by QingDao Nature Easy Soft Network Technology Co,LTD. (,www.cnezsoft.com).
|
||||
Anyone can use the agreement to publish open source software, and modify the blank underlined part of the following text of the agreement accordingly.
|
||||
No other text of the agreement shall be changed. QingDao Nature Easy Soft Network Technology Co,LTD has the final authority to interpret the terms of the agreement.
|
||||
Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by EasyCorp(en.easycorp.ltd).
|
||||
Anyone can use the agreement to publish open source software, and modify the blank in the following text of the agreement accordingly.
|
||||
No other text of the agreement shall be changed. EasyCorp has the final interpretation of the terms in the agreement.
|
||||
|
||||
Preface
|
||||
|
||||
ZenTaoPMS (Hereinafter referred to as "the software") developed by Nature EasySoft Network Tecnology Co.ltd, QingDao, China (www.cnezsoft.com) (hereinafter referred to I). I'm entitled to all copyright of the software.
|
||||
ZenTao ALM (Hereinafter referred to as "the software") developed by EasyCorp (en.easycorp.ltd) (hereinafter referred to I). I'm entitled to all copyright of the software.
|
||||
The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement.
|
||||
By installation of the software, you agree that a contractual relationship between you and me is automatically established.
|
||||
You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional contracts with me.
|
||||
You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional agreement with me.
|
||||
|
||||
My Contact:
|
||||
Email: co@easysoft.ltd
|
||||
Email: renee@easysoft.ltd
|
||||
Site: http://www.zentao.pm
|
||||
|
||||
We agree:
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
<?php
|
||||
class Git
|
||||
class ParseGit
|
||||
{
|
||||
public $client;
|
||||
public $root;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param string $client
|
||||
* @param string $root
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($client, $root, $username, $password, $encoding = 'UTF-8')
|
||||
{
|
||||
putenv('LC_CTYPE=en_US.UTF-8');
|
||||
@@ -16,6 +27,14 @@ class Git
|
||||
exec("{$this->client} config core.quotepath false");
|
||||
}
|
||||
|
||||
/**
|
||||
* List files.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
@@ -29,7 +48,7 @@ class Git
|
||||
|
||||
$infos = array();
|
||||
foreach($list as $entry)
|
||||
{
|
||||
{
|
||||
list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry);
|
||||
|
||||
/* Get commit info. */
|
||||
@@ -70,6 +89,29 @@ class Git
|
||||
return $infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function tags($path, $revision = 'HEAD')
|
||||
{
|
||||
chdir($this->root);
|
||||
$cmd = escapeCmd("$this->client tag --sort=taggerdate");
|
||||
$list = execCmd($cmd . ' 2>&1', 'array', $result);
|
||||
if($result) return array();
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branch
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function branch()
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -92,6 +134,14 @@ class Git
|
||||
return $branches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
@@ -104,6 +154,16 @@ class Git
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logs
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
@@ -116,7 +176,7 @@ class Git
|
||||
$logs = array();
|
||||
chdir($this->root);
|
||||
|
||||
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status -1 $fromRevision -- $path"), 'array');
|
||||
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 -1 $fromRevision -- $path"), 'array');
|
||||
$logs = $this->parseLog($list);
|
||||
return $logs;
|
||||
}
|
||||
@@ -130,12 +190,20 @@ class Git
|
||||
$revisions = "$fromRevision..$toRevision";
|
||||
}
|
||||
chdir($this->root);
|
||||
$list = execCmd(escapeCmd("$this->client log $count $revisions -- $path"), 'array');
|
||||
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 $count $revisions -- $path"), 'array');
|
||||
$logs = $this->parseLog($list);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
@@ -178,6 +246,15 @@ class Git
|
||||
return $blames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function diff($path, $fromRevision, $toRevision)
|
||||
{
|
||||
$path = ltrim($path, DIRECTORY_SEPARATOR);
|
||||
@@ -193,6 +270,14 @@ class Git
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cat file.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -203,6 +288,14 @@ class Git
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function info($entry, $revision = 'HEAD')
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -235,6 +328,13 @@ class Git
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse diff.
|
||||
*
|
||||
* @param array $lines
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseDiff($lines)
|
||||
{
|
||||
if(empty($lines)) return array();
|
||||
@@ -323,6 +423,14 @@ class Git
|
||||
return $diffs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commit count.
|
||||
*
|
||||
* @param int $commits
|
||||
* @param string $lastVersion
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getCommitCount($commits = 0, $lastVersion = '')
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -330,6 +438,12 @@ class Git
|
||||
return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first revision.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstRevision()
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -337,6 +451,12 @@ class Git
|
||||
return $list[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest revision
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getLatestRevision()
|
||||
{
|
||||
chdir($this->root);
|
||||
@@ -345,6 +465,15 @@ class Git
|
||||
return $list[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commits.
|
||||
*
|
||||
* @param string $version
|
||||
* @param int $count
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCommits($version = '', $count = 0, $branch = '')
|
||||
{
|
||||
if($version == 'HEAD' and $branch) $version = $branch;
|
||||
@@ -397,6 +526,13 @@ class Git
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse log.
|
||||
*
|
||||
* @param array $logs
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseLog($logs)
|
||||
{
|
||||
$parsedLogs = array();
|
||||
+135
-1
@@ -3,38 +3,110 @@ class scm
|
||||
{
|
||||
public $engine;
|
||||
|
||||
/**
|
||||
* Set engine.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setEngine($repo)
|
||||
{
|
||||
$className = $repo->SCM;
|
||||
if($className == 'Git') $className = 'ParseGit';
|
||||
if(!class_exists($className)) require(strtolower($className) . '.class.php');
|
||||
$this->engine = new $className($repo->client, $repo->path, $repo->account, $repo->password, $repo->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* List files.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->ls($path, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @param bool $onlyDir
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function tags($path, $revision, $onlyDir = true)
|
||||
{
|
||||
return $this->engine->tags($path, $revision, $onlyDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branch.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function branch()
|
||||
{
|
||||
return $this->engine->branch();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
|
||||
{
|
||||
return $this->engine->log($path, $fromRevision, $toRevision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
return $this->engine->blame($path, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
return $this->engine->getLastLog($path, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param string $parse
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function diff($path, $fromRevision = 0, $toRevision = 'HEAD', $parse = 'yes')
|
||||
{
|
||||
$diffs = $this->engine->diff($path, $fromRevision, $toRevision);
|
||||
@@ -43,37 +115,89 @@ class scm
|
||||
return $this->engine->parseDiff($diffs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cat file.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->cat($entry, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function info($entry, $revision = 'HEAD')
|
||||
{
|
||||
return $this->engine->info($entry, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commit count
|
||||
*
|
||||
* @param int $commits
|
||||
* @param string $lastVersion
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getCommitCount($commits = 0, $lastVersion = 0)
|
||||
{
|
||||
return $this->engine->getCommitCount($commits, $lastVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest revision.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getLatestRevision()
|
||||
{
|
||||
return $this->engine->getLatestRevision();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first revision.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstRevision()
|
||||
{
|
||||
return $this->engine->getFirstRevision();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commits.
|
||||
*
|
||||
* @param string $version
|
||||
* @param int $count
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCommits($version = '', $count = 0, $branch = '')
|
||||
{
|
||||
return $this->engine->getCommits($version, $count, $branch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function escapeCmd($cmd)
|
||||
{
|
||||
$codes = array('#', '&', ';', '`', '|', '*', '?', '~', '<', '>', '^', '[', ']', '{', '}', '$', ',', '\x0A', '\xFF');
|
||||
@@ -82,6 +206,16 @@ function escapeCmd($cmd)
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @param string $return
|
||||
* @param int $result
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return array|string
|
||||
*/
|
||||
function execCmd($cmd, $return = 'string', &$result = 0, $type = 'utf-8')
|
||||
{
|
||||
if(file_exists(dirname(__FILE__) . '/config.php')) include dirname(__FILE__) . '/config.php';
|
||||
|
||||
@@ -9,6 +9,17 @@ class Subversion
|
||||
public $remote;
|
||||
public $encoding;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param string $client
|
||||
* @param string $root
|
||||
* @param string $account
|
||||
* @param string $password
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($client, $root, $account, $password, $encoding = 'UTF-8')
|
||||
{
|
||||
putenv('LC_CTYPE=en_US.UTF-8');
|
||||
@@ -22,6 +33,14 @@ class Subversion
|
||||
if($this->encoding == 'utf-8') $this->encoding = 'gbk';
|
||||
}
|
||||
|
||||
/**
|
||||
* List files.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function ls($path, $revision = 'HEAD')
|
||||
{
|
||||
$resourcePath = $path;
|
||||
@@ -65,11 +84,47 @@ class Subversion
|
||||
return $infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @param bool $onlyDir
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function tags($path, $revision = 'HEAD', $onlyDir = true)
|
||||
{
|
||||
$infos = $this->ls($path, $revision);
|
||||
$tags = array();
|
||||
foreach($infos as $info)
|
||||
{
|
||||
if($onlyDir and $info->kind != 'dir') continue;
|
||||
$tags[$info->name] = $info->name;
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branch.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function branch()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLastLog($path, $count = 10)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
@@ -110,6 +165,17 @@ class Subversion
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param int $count
|
||||
* @param bool $quiet
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0, $quiet = false)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
@@ -165,6 +231,14 @@ class Subversion
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function blame($path, $revision)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
@@ -225,6 +299,15 @@ class Subversion
|
||||
return $blames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $fromRevision
|
||||
* @param int $toRevision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function diff($path, $fromRevision, $toRevision)
|
||||
{
|
||||
$resourcePath = $path;
|
||||
@@ -241,6 +324,14 @@ class Subversion
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cat file.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
$resourcePath = $entry;
|
||||
@@ -256,16 +347,26 @@ class Subversion
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
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 = '';
|
||||
}
|
||||
@@ -285,6 +386,13 @@ class Subversion
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse diff.
|
||||
*
|
||||
* @param array $lines
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseDiff($lines)
|
||||
{
|
||||
if(empty($lines)) return array();
|
||||
@@ -358,6 +466,14 @@ class Subversion
|
||||
return $diffs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commit count.
|
||||
*
|
||||
* @param int $commits
|
||||
* @param int $lastVersion
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getCommitCount($commits = 0, $lastVersion = 0)
|
||||
{
|
||||
if(empty($commits)) $commits = 0;
|
||||
@@ -381,6 +497,12 @@ class Subversion
|
||||
return $commits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first revision.
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getFirstRevision()
|
||||
{
|
||||
$logs = $this->log('', 0, 'HEAD', 1, $quiet = true);
|
||||
@@ -389,12 +511,26 @@ class Subversion
|
||||
return $firstLog->revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest revision.
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getLatestRevision()
|
||||
{
|
||||
$info = $this->info('');
|
||||
return $info->cRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commits.
|
||||
*
|
||||
* @param string $version
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCommits($version = '', $count = 0)
|
||||
{
|
||||
$count = $count == 0 ? '' : "--limit $count";
|
||||
@@ -443,11 +579,27 @@ class Subversion
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace svn auth.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function replaceAuth($cmd)
|
||||
{
|
||||
return str_replace(array('@account@', '@password@'), array($this->account, $this->password), $cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build command.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $action
|
||||
* @param string $param
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildCMD($path, $action, $param)
|
||||
{
|
||||
if($this->ssh)
|
||||
|
||||
@@ -143,21 +143,20 @@ class backup extends control
|
||||
$backupFiles = glob("{$this->backupPath}*.*");
|
||||
if(!empty($backupFiles))
|
||||
{
|
||||
$time = time();
|
||||
$time = time();
|
||||
$zfile = $this->app->loadClass('zfile');
|
||||
foreach($backupFiles as $file)
|
||||
{
|
||||
if($time - filemtime($file) > $this->config->backup->holdDays * 24 * 3600) unlink($file);
|
||||
if($time - filemtime($file) > $this->config->backup->holdDays * 24 * 3600)
|
||||
{
|
||||
$rmFunc = is_file($file) ? 'removeFile' : 'removeDir';
|
||||
$zfile->{$rmFunc}($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($reload == 'yes')
|
||||
{
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $this->lang->backup->success->backup . "\n";
|
||||
}
|
||||
if($reload == 'yes') die(js::reload('parent'));
|
||||
echo $this->lang->backup->success->backup . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+15
-2
@@ -541,10 +541,11 @@ class bug extends control
|
||||
* View a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param string $form
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view($bugID)
|
||||
public function view($bugID, $from = 'bug')
|
||||
{
|
||||
/* Judge bug exits or not. */
|
||||
$bug = $this->bug->getById($bugID, true);
|
||||
@@ -555,7 +556,18 @@ class bug extends control
|
||||
if($bug->assignedTo == $this->app->user->account) $this->loadModel('action')->read('bug', $bugID);
|
||||
|
||||
/* Set menu. */
|
||||
$this->bug->setMenu($this->products, $bug->product, $bug->branch);
|
||||
if($from == 'bug')
|
||||
{
|
||||
$this->bug->setMenu($this->products, $bug->product, $bug->branch);
|
||||
}
|
||||
elseif($from == 'repo')
|
||||
{
|
||||
session_write_close();
|
||||
$this->lang->set('menugroup.bug', 'repo');
|
||||
$repos = $this->loadModel('repo')->getRepoPairs();
|
||||
$this->repo->setMenu($repos);
|
||||
$this->lang->bug->menu = $this->lang->repo->menu;
|
||||
}
|
||||
|
||||
/* Get product info. */
|
||||
$productID = $bug->product;
|
||||
@@ -576,6 +588,7 @@ class bug extends control
|
||||
$this->view->modulePath = $this->tree->getParents($bug->module);
|
||||
$this->view->bugModule = empty($bug->module) ? '' : $this->tree->getById($bug->module);
|
||||
$this->view->bug = $bug;
|
||||
$this->view->from = $from;
|
||||
$this->view->branchName = $this->session->currentProductType == 'normal' ? '' : zget($branches, $bug->branch, '');
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->actions = $this->action->getList('bug', $bugID);
|
||||
|
||||
@@ -154,7 +154,7 @@ $lang->bug->lblLastEdited = '最后修改';
|
||||
$lang->bug->lblResolved = '由谁解决';
|
||||
$lang->bug->allUsers = '加载所有用户';
|
||||
$lang->bug->allBuilds = '所有';
|
||||
$lang->bug->createBuild = '新建';
|
||||
$lang->bug->createBuild = '创建';
|
||||
|
||||
/* legend列表。*/
|
||||
$lang->bug->legendBasicInfo = '基本信息';
|
||||
|
||||
@@ -154,7 +154,7 @@ $lang->bug->lblLastEdited = '最後修改';
|
||||
$lang->bug->lblResolved = '由誰解決';
|
||||
$lang->bug->allUsers = '加載所有用戶';
|
||||
$lang->bug->allBuilds = '所有';
|
||||
$lang->bug->createBuild = '新建';
|
||||
$lang->bug->createBuild = '创建';
|
||||
|
||||
/* legend列表。*/
|
||||
$lang->bug->legendBasicInfo = '基本信息';
|
||||
|
||||
@@ -181,6 +181,7 @@ class bugModel extends model
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$branch = (int)$branch;
|
||||
$productID = (int)$productID;
|
||||
$now = helper::now();
|
||||
$actions = array();
|
||||
$data = fixer::input('post')->get();
|
||||
|
||||
@@ -579,6 +579,7 @@ class caselibModel extends model
|
||||
$this->loadModel('action');
|
||||
|
||||
$now = helper::now();
|
||||
$libID = (int)$libID;
|
||||
$cases = fixer::input('post')->get();
|
||||
$batchNum = count(reset($cases));
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* The control file of ci module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package product
|
||||
* @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class ci extends control
|
||||
{
|
||||
/**
|
||||
* ci constructor.
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
parent::__construct($moduleName, $methodName);
|
||||
$this->ci->setMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build today job.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function buildTodayJob()
|
||||
{
|
||||
$scheduleJobs = $this->loadModel('integration')->getListByTriggerType('schedule');
|
||||
|
||||
$week = date('w');
|
||||
$this->loadModel('compile');
|
||||
foreach($scheduleJobs as $job)
|
||||
{
|
||||
if(strpos($job->scheduleDay, $week) !== false) $this->compile->createByIntegration($job->id);
|
||||
}
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec compile.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
$compiles = $this->loadModel('compile')->getUnexecutedList();
|
||||
foreach($compiles as $compile) $this->compile->execByCompile($compile);
|
||||
|
||||
$integrations = $this->loadModel('integration')->getListByTriggerType('tag');
|
||||
|
||||
$repoIdList = array();
|
||||
$repos = array();
|
||||
foreach($integrations as $integration) $repoIdList[$integration->id] = $integration->id;
|
||||
if($repoIdList) $repos = $this->loadModel('repo')->getByIdList($repoIdList);
|
||||
|
||||
foreach($integrations as $integration)
|
||||
{
|
||||
$repo = zget($repos, $integration->repo, null);
|
||||
if(empty($repo)) continue;
|
||||
|
||||
$scm = $repo->SCM == 'Git' ? 'git' : 'svn';
|
||||
$savedTag = $this->loadModel($scm)->getSavedTag($repo->id);
|
||||
|
||||
$tags = $this->$scm->getRepoTags($repo, $scm == 'svn' ? $integration->svnFolder : '');
|
||||
if(!empty($tags))
|
||||
{
|
||||
$arriveLastTag = false;
|
||||
foreach($tags as $tag)
|
||||
{
|
||||
/* Get the last build tag position */
|
||||
if($scm == 'git')
|
||||
{
|
||||
if(!empty($savedTag) && !$arriveLastTag) continue;
|
||||
if(!empty($savedTag) && $tag == $savedTag)
|
||||
{
|
||||
$arriveLastTag = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
elseif($scm == 'svn')
|
||||
{
|
||||
if(isset($savedTag[$tag])) continue;
|
||||
$tag = rtrim($repo->path , '/') . '/' . trim($integration->svnFolder, '/') . '/' . $tag;
|
||||
}
|
||||
|
||||
$tagData = new stdclass();
|
||||
$tagData->PARAM_TAG = $tag;
|
||||
$this->compile->execByIntegration($integration->id, $tagData);
|
||||
}
|
||||
|
||||
if($scm == 'svn') $tag = json_encode($tags);
|
||||
$this->$scm->saveLastTag($tag, $repo->id);
|
||||
}
|
||||
}
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to jenkins to check build status.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkBuildStatus()
|
||||
{
|
||||
$this->ci->checkBuildStatus();
|
||||
if(dao::isError())
|
||||
{
|
||||
echo json_encode(dao::getError());
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'success';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
$lang->ci->common = 'CI';
|
||||
$lang->ci->at = ' at ';
|
||||
$lang->ci->job = 'Job';
|
||||
$lang->ci->task = 'Job';
|
||||
$lang->ci->history = 'Build';
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
$lang->ci->common = '持续集成';
|
||||
$lang->ci->at = '于';
|
||||
$lang->ci->job = '构建';
|
||||
$lang->ci->task = '任务';
|
||||
$lang->ci->history = '历史';
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* The model file of ci module of ZenTaoPMS.
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package product
|
||||
* @version $Id: $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
|
||||
class ciModel extends model
|
||||
{
|
||||
/**
|
||||
* Set menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMenu()
|
||||
{
|
||||
$repoID = $this->session->repoID;
|
||||
$moduleName = $this->app->getModuleName();
|
||||
foreach($this->lang->{$moduleName}->menu as $key => $menu) common::setMenuVars($this->lang->{$moduleName}->menu, $key, $repoID);
|
||||
$this->lang->{$moduleName}->menuOrder = $this->lang->ci->menuOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to jenkins to check build status.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkBuildStatus()
|
||||
{
|
||||
$compiles = $this->dao->select('t1.*, t2.jenkinsJob, t3.name jenkinsName,t3.serviceUrl,t3.account,t3.token,t3.password')
|
||||
->from(TABLE_COMPILE)->alias('t1')
|
||||
->leftJoin(TABLE_INTEGRATION)->alias('t2')->on('t1.cijob=t2.id')
|
||||
->leftJoin(TABLE_JENKINS)->alias('t3')->on('t2.jenkins=t3.id')
|
||||
->where('t1.status')->ne('success')
|
||||
->andWhere('t1.status')->ne('fail')
|
||||
->andWhere('t1.status')->ne('timeout')
|
||||
->andWhere('t1.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
|
||||
->fetchAll();
|
||||
|
||||
foreach($compiles as $compile)
|
||||
{
|
||||
$jenkinsServer = $compile->serviceUrl;
|
||||
$jenkinsUser = $compile->account;
|
||||
$jenkinsPassword = $compile->token ? $compile->token : base64_decode($compile->password);
|
||||
|
||||
$jenkinsAuth = '://' . $jenkinsUser . ':' . $jenkinsPassword . '@';
|
||||
$jenkinsServer = str_replace('://', $jenkinsAuth, $jenkinsServer);
|
||||
$queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $compile->queueItem);
|
||||
|
||||
$response = common::http($queueUrl);
|
||||
if(strripos($response, "404") > -1)
|
||||
{
|
||||
/* Queue expired, use another api. */
|
||||
$infoUrl = sprintf('%s/job/%s/%s/api/json', $jenkinsServer, $compile->jenkinsJob, $compile->queueItem);
|
||||
$response = common::http($infoUrl);
|
||||
$buildInfo = json_decode($response);
|
||||
$result = strtolower($buildInfo->result);
|
||||
$this->updateBuildStatus($compile, $result);
|
||||
|
||||
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $compile->jenkinsJob, $compile->queueItem);
|
||||
$response = common::http($logUrl);
|
||||
$logs = json_decode($response);
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
$queueInfo = json_decode($response);
|
||||
if(!empty($queueInfo->executable))
|
||||
{
|
||||
$buildUrl = $queueInfo->executable->url . 'api/json?pretty=true';
|
||||
$buildUrl = str_replace('://', $jenkinsAuth, $buildUrl);
|
||||
|
||||
$response = common::http($buildUrl);
|
||||
$buildInfo = json_decode($response);
|
||||
|
||||
if($buildInfo->building)
|
||||
{
|
||||
$this->updateBuildStatus($compile, 'building');
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = strtolower($buildInfo->result);
|
||||
$this->updateBuildStatus($compile, $result);
|
||||
|
||||
$logUrl = $buildInfo->url . 'logText/progressiveText/api/json';
|
||||
$logUrl = str_replace('://', $jenkinsAuth, $logUrl);
|
||||
|
||||
$response = common::http($logUrl);
|
||||
$logs = json_decode($response);
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ci build status.
|
||||
*
|
||||
* @param object $build
|
||||
* @param string $status
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function updateBuildStatus($build, $status)
|
||||
{
|
||||
$this->dao->update(TABLE_COMPILE)->set('status')->eq($status)->where('id')->eq($build->id)->exec();
|
||||
$this->dao->update(TABLE_INTEGRATION)->set('lastExec')->eq(helper::now())->set('lastStatus')->eq($status)->where('id')->eq($build->cijob)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @return false|mixed|string
|
||||
*/
|
||||
public function sendRequest($url, $data)
|
||||
{
|
||||
if(!empty($data->PARAM_TAG)) $data->PARAM_REVISION = '';
|
||||
|
||||
$response = common::http($url, $data, true);
|
||||
if(preg_match("!Location: .*item/(.*)/!", $response, $matches)) return $matches[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,7 @@ $lang->loading = 'Loading...';
|
||||
$lang->notFound = 'Not found!';
|
||||
$lang->notPage = 'Sorry, the features you are visiting are in development!';
|
||||
$lang->showAll = '[[Show All]]';
|
||||
$lang->selectedItems = 'Seleted <strong>{0}</strong> items';
|
||||
|
||||
$lang->future = 'Waiting';
|
||||
$lang->year = 'Year';
|
||||
@@ -122,7 +123,7 @@ $lang->menu->my = '<span>Dashboard</span>|my|index';
|
||||
$lang->menu->product = $lang->productCommon . '|product|index|locate=no';
|
||||
$lang->menu->project = $lang->projectCommon . '|project|index|locate=no';
|
||||
$lang->menu->qa = 'Test|qa|index';
|
||||
$lang->menu->repo = 'Code|repo|log';
|
||||
$lang->menu->ci = 'CI|repo|browse';
|
||||
$lang->menu->doc = 'Doc|doc|index';
|
||||
$lang->menu->report = 'Report|report|index';
|
||||
$lang->menu->company = 'Company|company|index';
|
||||
@@ -331,11 +332,17 @@ $lang->caselib->menu->testsuite = array('link' => 'Suite|testsuite|browse|');
|
||||
$lang->caselib->menu->report = array('link' => 'Report|testreport|browse|');
|
||||
$lang->caselib->menu->caselib = array('link' => 'Case Library|caselib|browse|libID=%s', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
|
||||
|
||||
$lang->repo = new stdclass();
|
||||
$lang->repo->menu = new stdclass();
|
||||
$lang->repo->menu->browse = array('link' =>'Browse|repo|log|repoID=%s&entry=', 'alias' => 'diff,view,revision,showsynccomment');
|
||||
$lang->repo->menu->settings = 'Settings|repo|settings|repoID=%s';
|
||||
$lang->repo->menu->delete = array('link' => 'Delete|repo|delete|repoID=%s', 'target' => 'hiddenwin');
|
||||
$lang->ci = new stdclass();
|
||||
$lang->ci->menu = new stdclass();
|
||||
$lang->ci->menu->browse = array('link' =>'Code|repo|browse|repoID=%s', 'alias' => 'diff,view,revision,log,blame,showsynccomment');
|
||||
$lang->ci->menu->job = array('link' =>'Build|ci|browsejob', 'alias' => 'createjob,editjob,browsebuild,viewbuildlogs');
|
||||
$lang->ci->menu->maintain = array('link' =>'Repo|repo|maintain', 'alias' => 'create,edit');
|
||||
$lang->ci->menu->jenkins = array('link' =>'Jenkins|jenkins|browse', 'alias' => 'create,edit');
|
||||
|
||||
$lang->repo = new stdclass();
|
||||
$lang->jenkins = new stdclass();
|
||||
$lang->repo->menu = $lang->ci->menu;
|
||||
$lang->jenkins->menu = $lang->ci->menu;
|
||||
|
||||
/* Doc menu settings. */
|
||||
$lang->doc = new stdclass();
|
||||
@@ -475,6 +482,9 @@ $lang->menugroup->entry = 'admin';
|
||||
$lang->menugroup->webhook = 'admin';
|
||||
$lang->menugroup->message = 'admin';
|
||||
|
||||
$lang->menugroup->repo = 'ci';
|
||||
$lang->menugroup->jenkins = 'ci';
|
||||
|
||||
/* Error info. */
|
||||
$lang->error = new stdclass();
|
||||
$lang->error->companyNotFound = "The domain %s cannot be found!";
|
||||
@@ -501,6 +511,7 @@ $lang->error->pasteImg = 'Images are not allowed to be pasted in your bro
|
||||
$lang->error->noData = 'No data.';
|
||||
$lang->error->editedByOther = 'This record might have been changed. Please refresh and try to edit again!';
|
||||
$lang->error->tutorialData = 'No data can be imported in tutorial mode. Please quit tutorial first!';
|
||||
$lang->error->noCurlExt = 'No Curl module installed';
|
||||
|
||||
/* Page info. */
|
||||
$lang->pager = new stdclass();
|
||||
|
||||
@@ -4,7 +4,7 @@ $lang->menuOrder[5] = 'my';
|
||||
$lang->menuOrder[10] = 'product';
|
||||
$lang->menuOrder[15] = 'project';
|
||||
$lang->menuOrder[20] = 'qa';
|
||||
$lang->menuOrder[25] = 'repo';
|
||||
$lang->menuOrder[25] = 'ci';
|
||||
$lang->menuOrder[30] = 'doc';
|
||||
$lang->menuOrder[35] = 'report';
|
||||
$lang->menuOrder[40] = 'company';
|
||||
@@ -77,9 +77,14 @@ $lang->testsuite->menuOrder = $lang->testcase->menuOrder;
|
||||
$lang->caselib->menuOrder = $lang->testcase->menuOrder;
|
||||
$lang->testreport->menuOrder = $lang->testcase->menuOrder;
|
||||
|
||||
$lang->repo->menuOrder[5] = 'browse';
|
||||
$lang->repo->menuOrder[15] = 'settings';
|
||||
$lang->repo->menuOrder[20] = 'delete';
|
||||
$lang->ci->menuOrder[5] = 'browse';
|
||||
$lang->ci->menuOrder[10] = 'job';
|
||||
$lang->ci->menuOrder[15] = 'maintain';
|
||||
$lang->ci->menuOrder[20] = 'jenkins';
|
||||
$lang->ci->menuOrder[25] = 'match';
|
||||
|
||||
$lang->repo->menuOrder = $lang->ci->menuOrder;
|
||||
$lang->jenkins->menuOrder = $lang->ci->menuOrder;
|
||||
|
||||
/* doc menu order. */
|
||||
$lang->doc->menuOrder[5] = 'list';
|
||||
|
||||
@@ -101,6 +101,7 @@ $lang->loading = '稍候...';
|
||||
$lang->notFound = '抱歉,您访问的对象并不存在!';
|
||||
$lang->notPage = '抱歉,您访问的功能正在开发中!';
|
||||
$lang->showAll = '[[全部显示]]';
|
||||
$lang->selectedItems = '已选择 <strong>{0}</strong> 项';
|
||||
|
||||
$lang->future = '未来';
|
||||
$lang->year = '年';
|
||||
@@ -122,7 +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->ci = '集成|repo|browse';
|
||||
$lang->menu->doc = '文档|doc|index';
|
||||
$lang->menu->report = '统计|report|index';
|
||||
$lang->menu->company = '组织|company|index';
|
||||
@@ -331,11 +332,22 @@ $lang->caselib->menu->testsuite = array('link' => '套件|testsuite|browse|');
|
||||
$lang->caselib->menu->report = array('link' => '报告|testreport|browse|');
|
||||
$lang->caselib->menu->caselib = array('link' => '用例库|caselib|browse|libID=%s', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
|
||||
|
||||
$lang->repo = new stdclass();
|
||||
$lang->repo->menu = new stdclass();
|
||||
$lang->repo->menu->browse = 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->ci = new stdclass();
|
||||
$lang->ci->menu = new stdclass();
|
||||
$lang->ci->menu->browse = array('link' =>'代码|repo|browse|repoID=%s', 'alias' => 'diff,view,revision,log,blame,showsynccomment');
|
||||
$lang->ci->menu->job = array('link' =>'构建|integration|browse', 'subModule' => 'compile,integration');
|
||||
$lang->ci->menu->maintain = array('link' =>'版本库|repo|maintain', 'alias' => 'create,edit');
|
||||
$lang->ci->menu->jenkins = array('link' =>'Jenkins|jenkins|browse', 'alias' => 'create,edit');
|
||||
$lang->ci->menu->match = array('link' =>'匹配设置|repo|setmatchcomment');
|
||||
|
||||
$lang->repo = new stdclass();
|
||||
$lang->jenkins = new stdclass();
|
||||
$lang->compile = new stdclass();
|
||||
$lang->integration = new stdclass();
|
||||
$lang->repo->menu = $lang->ci->menu;
|
||||
$lang->jenkins->menu = $lang->ci->menu;
|
||||
$lang->compile->menu = $lang->ci->menu;
|
||||
$lang->integration->menu = $lang->ci->menu;
|
||||
|
||||
/* 文档视图菜单设置。*/
|
||||
$lang->doc = new stdclass();
|
||||
@@ -381,7 +393,7 @@ $lang->admin->menu = new stdclass();
|
||||
$lang->admin->menu->index = array('link' => '首页|admin|index', 'alias' => 'register,certifytemail,certifyztmobile,ztcompany');
|
||||
$lang->admin->menu->message = array('link' => '通知|message|index', 'subModule' => 'message,mail,webhook');
|
||||
$lang->admin->menu->custom = array('link' => '自定义|custom|set', 'subModule' => 'custom');
|
||||
$lang->admin->menu->sso = array('link' => '集成|admin|sso');
|
||||
$lang->admin->menu->sso = array('link' => '集成|admin|sso', 'subModule' => '');
|
||||
$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
|
||||
$lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,entry');
|
||||
$lang->admin->menu->translate = array('link' => '翻译|dev|translate');
|
||||
@@ -475,6 +487,11 @@ $lang->menugroup->entry = 'admin';
|
||||
$lang->menugroup->webhook = 'admin';
|
||||
$lang->menugroup->message = 'admin';
|
||||
|
||||
$lang->menugroup->repo = 'ci';
|
||||
$lang->menugroup->jenkins = 'ci';
|
||||
$lang->menugroup->compile = 'ci';
|
||||
$lang->menugroup->integration = 'ci';
|
||||
|
||||
/* 错误提示信息。*/
|
||||
$lang->error = new stdclass();
|
||||
$lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。";
|
||||
@@ -501,6 +518,7 @@ $lang->error->pasteImg = '您的浏览器不支持粘贴图片!';
|
||||
$lang->error->noData = '没有数据';
|
||||
$lang->error->editedByOther = '该记录可能已经被改动。请刷新页面重新编辑!';
|
||||
$lang->error->tutorialData = '新手模式下不会插入数据,请退出新手模式操作';
|
||||
$lang->error->noCurlExt = '服务器未安装Curl模块。';
|
||||
|
||||
/* 分页信息。*/
|
||||
$lang->pager = new stdclass();
|
||||
|
||||
@@ -662,11 +662,8 @@ class commonModel extends model
|
||||
echo '<li>' . html::a(helper::createLink('my', 'index'), $lang->zentaoPMS) . '</li>';
|
||||
if($moduleName != 'index')
|
||||
{
|
||||
if(!isset($lang->menu->$mainMenu))
|
||||
{
|
||||
echo "</ul>";
|
||||
return;
|
||||
}
|
||||
if(!isset($lang->menu->$mainMenu)) return print("</ul>");
|
||||
|
||||
$menuLink = $lang->menu->$mainMenu;
|
||||
list($menuLabel, $module, $method) = explode('|', $menuLink);
|
||||
echo '<li>' . html::a(helper::createLink($module, $method), $menuLabel) . '</li>';
|
||||
@@ -1823,7 +1820,7 @@ EOD;
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function http($url, $data = null)
|
||||
public static function http($url, $data = null, $optHeader = false)
|
||||
{
|
||||
global $lang, $app;
|
||||
if(!extension_loaded('curl')) return json_encode(array('result' => 'fail', 'message' => $lang->error->noCurlExt));
|
||||
@@ -1844,6 +1841,7 @@ EOD;
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE);
|
||||
if($optHeader) curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
if(!empty($data))
|
||||
{
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* The control file of compile of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package compile
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class compile extends control
|
||||
{
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
parent::__construct($moduleName, $methodName);
|
||||
$this->loadModel('ci')->setMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse jenkins build.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($jobID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->compile->browse;
|
||||
$this->view->position[] = html::a($this->createLink('integration', 'browse'), $this->lang->ci->job);
|
||||
$this->view->position[] = $this->lang->compile->browse;
|
||||
|
||||
$this->view->buildList = $this->compile->getList($jobID, $orderBy, $pager);
|
||||
$this->view->job = $this->loadModel('integration')->getByID($jobID);
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->pager = $pager;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* View jenkins build logs.
|
||||
*
|
||||
* @param int $buildID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function logs($buildID)
|
||||
{
|
||||
$build = $this->compile->getByID($buildID);
|
||||
$this->view->logs = str_replace("\r\n","<br />", $build->logs);
|
||||
$this->view->build = $build;
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->compile->logs;
|
||||
$this->view->position[] = html::a($this->createLink('integration', 'browse'), $this->lang->ci->job);
|
||||
$this->view->position[] = html::a($this->createLink('compile', 'browse', "jobID=" . $build->cijob), $this->lang->compile->browse);
|
||||
$this->view->position[] = $this->lang->compile->logs;
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
$lang->compile->browse = 'Build Histories';
|
||||
$lang->compile->logs = 'Build Logs';
|
||||
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = 'Name';
|
||||
$lang->compile->status = 'Build Status';
|
||||
$lang->compile->time = 'Build Time';
|
||||
|
||||
$lang->compile->statusList['success'] = 'Success';
|
||||
$lang->compile->statusList['fail'] = 'Fail';
|
||||
$lang->compile->statusList['created'] = 'Created';
|
||||
$lang->compile->statusList['building'] = 'Building';
|
||||
$lang->compile->statusList['create_fail'] = 'Fail to create';
|
||||
$lang->compile->statusList['timeout'] = 'Exec Timeout';
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
$lang->compile->browse = '构建历史';
|
||||
$lang->compile->logs = '构建日志';
|
||||
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = '名称';
|
||||
$lang->compile->status = '构建状态';
|
||||
$lang->compile->time = '构建时间';
|
||||
|
||||
$lang->compile->statusList['success'] = '成功';
|
||||
$lang->compile->statusList['fail'] = '失败';
|
||||
$lang->compile->statusList['created'] = '新建';
|
||||
$lang->compile->statusList['building'] = '构建中';
|
||||
$lang->compile->statusList['create_fail'] = '创建失败';
|
||||
$lang->compile->statusList['timeout'] = '执行超时';
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* The model file of compile module of ZenTaoCMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package compile
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class compileModel extends model
|
||||
{
|
||||
/**
|
||||
* Get build list.
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getList($jobID, $orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
return $this->dao->select('t1.id, t1.name, t1.status, t1.createdDate, t2.triggerType, t3.name as repoName, t4.name as jenkinsName')->from(TABLE_COMPILE)->alias('t1')
|
||||
->leftJoin(TABLE_INTEGRATION)->alias('t2')->on('t1.cijob=t2.id')
|
||||
->leftJoin(TABLE_REPO)->alias('t3')->on('t2.repo=t3.id')
|
||||
->leftJoin(TABLE_JENKINS)->alias('t4')->on('t2.jenkins=t4.id')
|
||||
->where('t1.deleted')->eq('0')
|
||||
->andWhere('t1.cijob')->eq($jobID)
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get by id
|
||||
*
|
||||
* @param int $buildID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getByID($buildID)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_COMPILE)->where('id')->eq($buildID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unexecuted list.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getUnexecutedList()
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_COMPILE)->where('status')->eq('')->andWhere('deleted')->eq('0')->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save build by job
|
||||
*
|
||||
* @param object $job
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function createByIntegration($integrationID)
|
||||
{
|
||||
$integration = $this->dao->select('id,name')->from(TABLE_INTEGRATION)->where('id')->eq($integrationID)->fetch();
|
||||
|
||||
$build = new stdClass();
|
||||
$build->cijob = $integration->id;
|
||||
$build->name = $integration->name;
|
||||
$build->createdBy = $this->app->user->account;
|
||||
$build->createdDate = helper::now();
|
||||
|
||||
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute compile
|
||||
*
|
||||
* @param object $compile
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function execByCompile($compile, $data = null)
|
||||
{
|
||||
$integration = $this->dao->select('t1.id as jobId,t1.name as jobName,t1.repo,t1.jenkinsJob,t2.name as jenkinsName,t2.serviceUrl,t2.account,t2.token,t2.password')
|
||||
->from(TABLE_INTEGRATION)->alias('t1')
|
||||
->leftJoin(TABLE_JENKINS)->alias('t2')->on('t1.jenkins=t2.id')
|
||||
->where('t1.id')->eq($compile->cijob)
|
||||
->fetch();
|
||||
|
||||
if(!$integration) return false;
|
||||
|
||||
$buildUrl = $this->getBuildUrl($integration);
|
||||
$build = new stdclass();
|
||||
$build->queueItem = $this->loadModel('ci')->sendRequest($buildUrl, $data);
|
||||
$build->status = $build->queueItem ? 'created' : 'create_fail';
|
||||
$this->dao->update(TABLE_COMPILE)->data($build)->where('id')->eq($compile->id)->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute by integration.
|
||||
*
|
||||
* @param int $compile
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function execByIntegration($integrationID, $data = null)
|
||||
{
|
||||
$integration = $this->dao->select('t1.id as jobId,t1.name as jobName,t1.repo,t1.jenkinsJob,t2.name as jenkinsName,t2.serviceUrl,t2.account,t2.token,t2.password')
|
||||
->from(TABLE_INTEGRATION)->alias('t1')
|
||||
->leftJoin(TABLE_JENKINS)->alias('t2')->on('t1.jenkins=t2.id')
|
||||
->where('t1.id')->eq($integrationID)
|
||||
->fetch();
|
||||
|
||||
if(!$integration) return false;
|
||||
|
||||
$buildUrl = $this->getBuildUrl($integration);
|
||||
$build = new stdClass();
|
||||
$build->cijob = $integration->jobId;
|
||||
$build->name = $integration->jobName;
|
||||
$build->queueItem = $this->loadModel('ci')->sendRequest($buildUrl, $data);
|
||||
$build->status = $build->queueItem ? 'created' : 'create_fail';
|
||||
$build->createdBy = $this->app->user->account;
|
||||
$build->createdDate = helper::now();
|
||||
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get build url.
|
||||
*
|
||||
* @param object $jenkins
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getBuildUrl($jenkins)
|
||||
{
|
||||
$jenkinsServer = $jenkins->serviceUrl;
|
||||
$jenkinsUser = $jenkins->account;
|
||||
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
|
||||
|
||||
$jenkinsAuth = '://' . $jenkinsUser . ':' . $jenkinsPassword . '@';
|
||||
$jenkinsServer = str_replace('://', $jenkinsAuth, $jenkinsServer);
|
||||
$buildUrl = sprintf('%s/job/%s/buildWithParameters/api/json', $jenkinsServer, $jenkins->jenkinsJob);
|
||||
return $buildUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* The browse view file of compile module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package compile
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php
|
||||
echo html::a($this->createLink('integration', 'browse'), "<span class='text'>{$lang->ci->task}</span>", '', "class='btn btn-link'");
|
||||
echo html::a($this->createLink('compile', 'browse'), "<span class='text'>{$lang->ci->history}</span>", '', "class='btn btn-link btn-active-text'");
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='mainContent'>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='buildList' class='table has-sort-head table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $vars = "jobID={$job->id}&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
|
||||
<th class='w-60px'><?php common::printOrderLink('id', $orderBy, $vars, $lang->compile->id);?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->compile->name);?></th>
|
||||
<th class='w-200px text-left'><?php echo $lang->integration->repo;?></th>
|
||||
<th class='w-200px text-left'><?php echo $lang->integration->jenkins;?></th>
|
||||
<th class='w-200px text-left'><?php echo $lang->integration->triggerType;?></th>
|
||||
<th class='w-150px text-left'><?php common::printOrderLink('status', $orderBy, $vars, $lang->compile->status);?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('createdDate', $orderBy, $vars, $lang->compile->time);?></th>
|
||||
<th class='w-100px c-actions-4'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($buildList as $id => $build): ?>
|
||||
<tr>
|
||||
<td class='text-center'><?php echo $id; ?></td>
|
||||
<td class='text' title='<?php echo $build->name; ?>'><?php echo $build->name; ?></td>
|
||||
<td class='text' title='<?php echo $build->repoName; ?>'><?php echo $build->repoName; ?></td>
|
||||
<td class='text' title='<?php echo $build->jenkinsName; ?>'><?php echo $build->jenkinsName; ?></td>
|
||||
<?php $triggerType = zget($lang->integration->triggerTypeList, $build->triggerType);?>
|
||||
<td class='text' title='<?php echo $triggerType;?>'><?php echo $triggerType;?></td>
|
||||
<?php $buildStatus = zget($lang->compile->statusList, $build->status);?>
|
||||
<td class='text' title='<?php echo $buildStatus;?>'><?php echo $buildStatus;?></td>
|
||||
<td class='text' title='<?php echo $build->createDate; ?>'><?php echo $build->createdDate; ?></td>
|
||||
<td class='c-actions text-center'>
|
||||
<?php common::printIcon('compile', 'logs', "buildID=$id", '', 'list', 'file-text', '', '', '', '', $lang->compile->logs);?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($buildList):?>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* The browse view file of compile module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package compile
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?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 $lang->compile->logs;?></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php echo html::a(helper::createLink('compile', "browse", "jobId=$build->cijob"), "<i class='icon icon-back icon-sm'></i> ". $lang->goback, '', "class='btn btn-secondary'");?>
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent'>
|
||||
<div class='main-content'><?php echo $logs;?></div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -211,9 +211,12 @@ class cron extends control
|
||||
}
|
||||
|
||||
/* Save log. */
|
||||
$log = '';
|
||||
$time = $now->format('G:i:s');
|
||||
$log = "$time task " . $id . " executed,\ncommand: $cron[command].\nreturn : $return.\noutput : $output\n";
|
||||
$log = '';
|
||||
$time = $now->format('G:i:s');
|
||||
$output = "\n";
|
||||
if(strlen($output) > 100) $output = "\n" . $output;
|
||||
|
||||
$log = "$time task " . $id . " executed,\ncommand: $cron[command].\nreturn : $return.\noutput : $output\n";
|
||||
$this->cron->logCron($log);
|
||||
unset($log);
|
||||
}
|
||||
|
||||
@@ -149,8 +149,7 @@ class file extends control
|
||||
/* Down the file. */
|
||||
$fileName = $file->title;
|
||||
if(!preg_match("/\.{$file->extension}$/", $fileName)) $fileName .= '.' . $file->extension;
|
||||
$fileData = file_get_contents($file->realPath);
|
||||
$this->sendDownHeader($fileName, $file->extension, $fileData);
|
||||
$this->sendDownHeader($fileName, $file->extension, $file->realPath, 'file');
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -244,9 +243,9 @@ class file extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function sendDownHeader($fileName, $fileType, $content)
|
||||
public function sendDownHeader($fileName, $fileType, $content, $type = 'content')
|
||||
{
|
||||
$this->file->sendDownHeader($fileName, $fileType, $content);
|
||||
$this->file->sendDownHeader($fileName, $fileType, $content, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+10
-2
@@ -869,7 +869,7 @@ class fileModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function sendDownHeader($fileName, $fileType, $content)
|
||||
public function sendDownHeader($fileName, $fileType, $content, $type = 'content')
|
||||
{
|
||||
/* Clean the ob content to make sure no space or utf-8 bom output. */
|
||||
$obLevel = ob_get_level();
|
||||
@@ -893,6 +893,14 @@ class fileModel extends model
|
||||
header("Content-Disposition: attachment; filename=\"$fileName\"");
|
||||
header("Pragma: no-cache");
|
||||
header("Expires: 0");
|
||||
die($content);
|
||||
if($type == 'content') die($content);
|
||||
if($type == 'file' and file_exists($content))
|
||||
{
|
||||
$chunkSize = 1024 * 1024;
|
||||
$handle = fopen($content, "r");
|
||||
while(!feof($handle)) echo fread($handle, $chunkSize);
|
||||
fclose($handle);
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,2 @@
|
||||
<?php
|
||||
/**
|
||||
* encodings: 提交日志的编码,比如GBK,可以用逗号连接起来的多个。
|
||||
* client: Git客户端执行文件的路径,windows下面是git.exe的路径,linux下面比如/usr/bin/git
|
||||
* repos可以是多个,需要设定某一个库的访问路径。
|
||||
*
|
||||
* encodeings: the encoding of the comment,can be a list.
|
||||
* client: the git client binary path. Unser windows, find the path of git.exe. Under linux, try /usr/bin/git
|
||||
* Can set multi repos, ervery one should set the path.
|
||||
*
|
||||
* 例子:
|
||||
* $config->git->client = '/usr/bin/git'; // c:\git\git.exe
|
||||
* $config->git->repos['pms']['path'] = '/home/user/repo/pms'; // c:\repo\pms
|
||||
*
|
||||
*/
|
||||
$config->git = new stdClass();
|
||||
$config->git->encodings = 'utf-8';
|
||||
$config->git->client = '';
|
||||
|
||||
$i = 1;
|
||||
$config->git->repos[$i]['path'] = '';
|
||||
$config->git->repos[$i]['encoding'] = 'utf-8';
|
||||
|
||||
/*
|
||||
$i ++;
|
||||
$config->git->repos[$i]['path'] = '';
|
||||
*/
|
||||
|
||||
@@ -37,10 +37,9 @@ class git extends control
|
||||
$path = helper::safe64Decode($path);
|
||||
if(common::hasPriv('repo', 'diff'))
|
||||
{
|
||||
$repos = $this->loadModel('repo')->getAllRepos();
|
||||
$repos = $this->loadModel('repo')->getListBySCM('Git', 'haspriv');
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
if($repo->SCM != 'Git') continue;
|
||||
if(strpos($path, $repo->path) === 0)
|
||||
{
|
||||
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
|
||||
@@ -72,10 +71,9 @@ class git extends control
|
||||
$path = helper::safe64Decode($path);
|
||||
if(common::hasPriv('repo', 'view'))
|
||||
{
|
||||
$repos = $this->loadModel('repo')->getAllRepos();
|
||||
$repos = $this->loadModel('repo')->getListBySCM('Git', 'haspriv');
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
if($repo->SCM != 'Git') continue;
|
||||
if(strpos($path, $repo->path) === 0)
|
||||
{
|
||||
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
|
||||
@@ -121,9 +119,11 @@ class git extends control
|
||||
}
|
||||
|
||||
$parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array());
|
||||
$this->loadModel('repo');
|
||||
foreach($parsedLogs as $log)
|
||||
{
|
||||
$objects = $this->git->parseComment($log->msg);
|
||||
$objects = $this->repo->parseComment($log->msg);
|
||||
|
||||
if($objects)
|
||||
{
|
||||
$this->git->saveAction2PMS($objects, $log, $repoRoot);
|
||||
@@ -181,7 +181,8 @@ class git extends control
|
||||
$parsedFiles[$action][] = ltrim($path, '/');
|
||||
}
|
||||
|
||||
$objects = $this->git->parseComment($message);
|
||||
$objects = $this->loadModel('repo')->parseComment($message);
|
||||
|
||||
if($objects)
|
||||
{
|
||||
$log = new stdclass();
|
||||
|
||||
+165
-150
@@ -71,6 +71,7 @@ class gitModel extends model
|
||||
{
|
||||
parent::__construct();
|
||||
$this->loadModel('action');
|
||||
$this->loadModel('repo');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,51 +88,59 @@ class gitModel extends model
|
||||
$this->setLogRoot();
|
||||
$this->setRestartFile();
|
||||
|
||||
foreach($this->repos as $name => $repo)
|
||||
foreach($this->repos as $repo)
|
||||
{
|
||||
$this->printLog("begin repo $name");
|
||||
$repo = (object)$repo;
|
||||
$repo->name = $name;
|
||||
$this->printLog("begin repo $repo->id");
|
||||
if(!$this->setRepo($repo)) return false;
|
||||
|
||||
$savedRevision = $this->getSavedRevision();
|
||||
$this->printLog("start from revision $savedRevision");
|
||||
$logs = $this->getRepoLogs($repo, $savedRevision);
|
||||
if(empty($logs)) continue;
|
||||
|
||||
$this->printLog("get " . count($logs) . " logs");
|
||||
$this->printLog('begin parsing logs');
|
||||
$latestRevision = $logs[0]->revision;
|
||||
foreach($logs as $log)
|
||||
$logs = $this->getRepoLogs($repo, $savedRevision);
|
||||
$objects = array();
|
||||
if(!empty($logs))
|
||||
{
|
||||
$this->printLog("parsing log {$log->revision}");
|
||||
if($log->revision == $savedRevision)
|
||||
$this->printLog("get " . count($logs) . " logs");
|
||||
$this->printLog('begin parsing logs');
|
||||
$latestRevision = $logs[0]->revision;
|
||||
|
||||
foreach($logs as $log)
|
||||
{
|
||||
$this->printLog("{$log->revision} alread parsed, commit it");
|
||||
continue;
|
||||
$this->printLog("parsing log {$log->revision}");
|
||||
if($log->revision == $savedRevision)
|
||||
{
|
||||
$this->printLog("{$log->revision} alread parsed, commit it");
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------");
|
||||
|
||||
$objects = $this->repo->parseComment($log->msg);
|
||||
|
||||
if($objects)
|
||||
{
|
||||
$this->printLog('extract' .
|
||||
' story:' . join(' ', $objects['stories']) .
|
||||
' task:' . join(' ', $objects['tasks']) .
|
||||
' bug:' . join(',', $objects['bugs']));
|
||||
|
||||
$this->saveAction2PMS($objects, $log, $repo->encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->printLog('no objects found' . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
$this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------");
|
||||
$objects = $this->parseComment($log->msg);
|
||||
if($objects)
|
||||
{
|
||||
$this->printLog('extract' .
|
||||
' story:' . join(' ', $objects['stories']) .
|
||||
' task:' . join(' ', $objects['tasks']) .
|
||||
' bug:' . join(',', $objects['bugs']));
|
||||
|
||||
$this->saveAction2PMS($objects, $log);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->printLog('no objects found' . "\n");
|
||||
}
|
||||
$this->saveLastRevision($latestRevision);
|
||||
$this->printLog("save revision $latestRevision");
|
||||
$this->deleteRestartFile();
|
||||
$this->printLog("\n\nrepo #" . $repo->id . ': ' . $repo->path . " finished");
|
||||
}
|
||||
|
||||
$this->saveLastRevision($latestRevision);
|
||||
$this->printLog("save revision $latestRevision");
|
||||
$this->deleteRestartFile();
|
||||
$this->printLog("\n\nrepo $name finished");
|
||||
// exe ci jobs in log
|
||||
$cijobIdList = zget($objects, 'integrations', array());
|
||||
$this->loadModel('compile');
|
||||
foreach($cijobIdList as $id) $this->compile->execByIntegration($id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,13 +186,46 @@ class gitModel extends model
|
||||
*/
|
||||
public function setRepos()
|
||||
{
|
||||
if(!$this->config->git->repos)
|
||||
$repos = $this->loadModel('repo')->getListBySCM('Git');
|
||||
$gitRepos = array();
|
||||
$paths = array();
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
echo "You must set one git repo.\n";
|
||||
return false;
|
||||
if(!isset($paths[$repo->path]))
|
||||
{
|
||||
unset($repo->acl);
|
||||
unset($repo->desc);
|
||||
$gitRepos[] = $repo;
|
||||
$paths[$repo->path] = $repo->path;
|
||||
}
|
||||
}
|
||||
|
||||
$this->repos = $this->config->git->repos;
|
||||
if(isset($this->config->git->repos))
|
||||
{
|
||||
foreach($this->config->git->repos as $i => $repo)
|
||||
{
|
||||
$repoPath = $repo['path'];
|
||||
if(empty($repoPath)) continue;
|
||||
if(isset($paths[$repoPath])) continue;
|
||||
|
||||
$gitRepo = new stdclass();
|
||||
$gitRepo->id = "c{$i}";
|
||||
$gitRepo->client = $this->config->git->client;
|
||||
$gitRepo->path = $repoPath;
|
||||
$gitRepo->prefix = '';
|
||||
$gitRepo->SCM = 'Git';
|
||||
$gitRepo->account = '';
|
||||
$gitRepo->password = '';
|
||||
$gitRepo->encoding = zget($repo, 'encoding', $this->config->git->client);
|
||||
|
||||
$gitRepos[] = $gitRepo;
|
||||
$paths[$repoPath] = $repoPath;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($gitRepos)) echo "You must set one git repo.\n";
|
||||
|
||||
$this->repos = $gitRepos;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -195,15 +237,11 @@ class gitModel extends model
|
||||
*/
|
||||
public function getRepos()
|
||||
{
|
||||
$repos = array();
|
||||
if(!$this->config->git->repos) return $repos;
|
||||
$repos = $this->setRepos();
|
||||
$repoPairs = array();
|
||||
foreach($repos as $repo) $repoPairs[] = $repo->path;
|
||||
|
||||
foreach($this->config->git->repos as $repo)
|
||||
{
|
||||
if(empty($repo['path'])) continue;
|
||||
$repos[] = $repo['path'];
|
||||
}
|
||||
return $repos;
|
||||
return $repoPairs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,40 +256,49 @@ class gitModel extends model
|
||||
$this->setClient($repo);
|
||||
if(empty($this->client)) return false;
|
||||
|
||||
$this->setLogFile($repo->name);
|
||||
$this->setLogFile($repo->id);
|
||||
$this->setTagFile($repo->id);
|
||||
$this->setRepoRoot($repo);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the git binary client of a repo.
|
||||
*
|
||||
* @param object $repo
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function setClient($repo)
|
||||
{
|
||||
if($this->config->git->client == '')
|
||||
{
|
||||
echo "You must set the git client file.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->client = $this->config->git->client;
|
||||
$this->client = $repo->client;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the log file of a repo.
|
||||
*
|
||||
* @param string $repoName
|
||||
*
|
||||
* @param string $repoId
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setLogFile($repoName)
|
||||
public function setLogFile($repoId)
|
||||
{
|
||||
$this->logFile = $this->logRoot . $repoName;
|
||||
$this->logFile = $this->logRoot . $repoId . '.log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tag file of a repo.
|
||||
*
|
||||
* @param string $repoId
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setTagFile($repoId)
|
||||
{
|
||||
$this->setLogRoot();
|
||||
$this->tagFile = $this->logRoot . $repoId . '.tag';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,6 +313,20 @@ class gitModel extends model
|
||||
$this->repoRoot = $repo->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* get tags histories for repo.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getRepoTags($repo)
|
||||
{
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
return $scm->tags('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repo logs.
|
||||
*
|
||||
@@ -276,40 +337,22 @@ class gitModel extends model
|
||||
*/
|
||||
public function getRepoLogs($repo, $fromRevision)
|
||||
{
|
||||
$parsedLogs = array();
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
$logs = $scm->log('', $fromRevision);
|
||||
if(empty($logs)) return false;
|
||||
|
||||
/* The git log command. */
|
||||
chdir($this->repoRoot);
|
||||
exec("{$this->client} config core.quotepath false");
|
||||
if($fromRevision)
|
||||
foreach($logs as $log)
|
||||
{
|
||||
$cmd = "$this->client log --stat=1024 --stat-name-width=1000 --name-status $fromRevision..HEAD";
|
||||
}
|
||||
else
|
||||
{
|
||||
$cmd = "$this->client log --stat=1024 --stat-name-width=1000 --name-status";
|
||||
}
|
||||
exec($cmd, $list, $return);
|
||||
$log->author = $log->committer;
|
||||
$log->msg = $log->comment;
|
||||
$log->date = $log->time;
|
||||
|
||||
if(!$list and $return)
|
||||
{
|
||||
echo "Some error occers: \nThe command is $cmd\n";
|
||||
return false;
|
||||
/* Process files. */
|
||||
$log->files = array();
|
||||
foreach($log->change as $file => $info) $log->files[$info['action']][] = $file;
|
||||
}
|
||||
if(!$list and !$return) return array();
|
||||
|
||||
/* Process logs. */
|
||||
$logs = array();
|
||||
$i = 0;
|
||||
|
||||
foreach($list as $line)
|
||||
{
|
||||
if(strpos($line, 'commit ') === 0) $i++;
|
||||
$logs[$i][] = $line;
|
||||
}
|
||||
|
||||
foreach($logs as $log) $parsedLogs[] = $this->convertLog($log);
|
||||
return $parsedLogs;
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,63 +397,6 @@ class gitModel extends model
|
||||
return $parsedLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the comment of git, extract object id list from it.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseComment($comment)
|
||||
{
|
||||
$stories = array();
|
||||
$tasks = array();
|
||||
$bugs = array();
|
||||
|
||||
// bug|story|task(case insensitive) + some space + #|:|:(Chinese) + id lists(maybe join with space or ,)
|
||||
// $comment = "bug # 1,2,3,4 Bug:1 2 3 4 5 story:9999,1234566 story:456,1234566";
|
||||
$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)) $stories = join(' ', $result[1]);
|
||||
if(preg_match_all($taskReg, $comment, $result)) $tasks = join(' ', $result[1]);
|
||||
if(preg_match_all($bugReg, $comment, $result)) $bugs = join(' ', $result[1]);
|
||||
|
||||
if($stories) $stories = array_unique(explode(' ', str_replace(',', ' ', $stories)));
|
||||
if($tasks) $tasks = array_unique(explode(' ', str_replace(',', ' ', $tasks)));
|
||||
if($bugs) $bugs = array_unique(explode(' ', str_replace(',', ' ', $bugs)));
|
||||
|
||||
if(!$stories and !$tasks and !$bugs) return array();
|
||||
return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the comment to uft-8.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function iconvComment($comment)
|
||||
{
|
||||
/* Get encodings. */
|
||||
$encodings = str_replace(' ', '', isset($this->config->git->encodings) ? $this->config->git->encodings : '');
|
||||
if($encodings == '') return $comment;
|
||||
$encodings = explode(',', $encodings);
|
||||
|
||||
/* Try convert. */
|
||||
foreach($encodings as $encoding)
|
||||
{
|
||||
if($encoding == 'utf-8') continue;
|
||||
$result = helper::convertEncoding($comment, $encoding, 'utf-8');
|
||||
if($result) return $result;
|
||||
}
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff a url.
|
||||
*
|
||||
@@ -520,13 +506,14 @@ class gitModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveAction2PMS($objects, $log, $repoRoot = '')
|
||||
public function saveAction2PMS($objects, $log, $repoRoot = '', $encodings = 'utf-8')
|
||||
{
|
||||
$action = new stdclass();
|
||||
$action->actor = $log->author;
|
||||
$action->action = 'gitcommited';
|
||||
$action->date = $log->date;
|
||||
$action->comment = htmlspecialchars($this->iconvComment($log->msg));
|
||||
|
||||
$action->comment = htmlspecialchars($this->repo->iconvComment($log->msg, $encodings));
|
||||
$action->extra = substr($log->revision, 0, 10);
|
||||
|
||||
$changes = $this->createActionChanges($log, $repoRoot);
|
||||
@@ -738,7 +725,34 @@ class gitModel extends model
|
||||
*/
|
||||
public function saveLastRevision($revision)
|
||||
{
|
||||
file_put_contents($this->logFile, $revision);
|
||||
$ret = file_put_contents($this->logFile, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the saved tag.
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getSavedTag($repoID = 0)
|
||||
{
|
||||
if($repoID) $this->setTagFile($repoID);
|
||||
if(!file_exists($this->tagFile)) return 0;
|
||||
if(file_exists($this->restartFile)) return 0;
|
||||
return trim(file_get_contents($this->tagFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the last revision.
|
||||
*
|
||||
* @param int $tag
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveLastTag($tag, $repoId = 0)
|
||||
{
|
||||
if($repoId) $this->setTagFile($repoId);
|
||||
file_put_contents($this->tagFile, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -753,6 +767,7 @@ class gitModel extends model
|
||||
echo helper::now() . " $log\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build URL.
|
||||
*
|
||||
|
||||
@@ -686,8 +686,9 @@ $lang->resource->repo->browse = 'browse';
|
||||
$lang->resource->repo->view = 'view';
|
||||
$lang->resource->repo->log = 'log';
|
||||
$lang->resource->repo->revision = 'revisionAction';
|
||||
$lang->resource->repo->settings = 'settings';
|
||||
$lang->resource->repo->create = 'create';
|
||||
$lang->resource->repo->blame = 'blameAction';
|
||||
$lang->resource->repo->create = 'createAction';
|
||||
$lang->resource->repo->edit = 'editAction';
|
||||
$lang->resource->repo->delete = 'delete';
|
||||
$lang->resource->repo->showSyncComment = 'showSyncComment';
|
||||
$lang->resource->repo->diff = 'diffAction';
|
||||
|
||||
@@ -165,6 +165,9 @@ $lang->install->cronList['moduleName=mail&methodName=asyncSend'] = 'Asynchr
|
||||
$lang->install->cronList['moduleName=webhook&methodName=asyncSend'] = 'Asynchronize sending Webhook';
|
||||
$lang->install->cronList['moduleName=admin&methodName=deleteLog'] = 'Delete overdue logs';
|
||||
$lang->install->cronList['moduleName=todo&methodName=createCycle'] = 'Create recurring todos';
|
||||
$lang->install->cronList['moduleName=ci&methodName=buildTodayJob'] = 'Create recurring jenkins';
|
||||
$lang->install->cronList['moduleName=ci&methodName=checkBuildStatus'] = 'Synchronize Jenkins Status';
|
||||
$lang->install->cronList['moduleName=ci&methodName=exec'] = 'Execute Jenkins';
|
||||
|
||||
$lang->install->success = "Installed!";
|
||||
$lang->install->login = 'Login ZenTao';
|
||||
|
||||
@@ -165,6 +165,9 @@ $lang->install->cronList['moduleName=mail&methodName=asyncSend'] = '异步
|
||||
$lang->install->cronList['moduleName=webhook&methodName=asyncSend'] = '异步发送Webhook';
|
||||
$lang->install->cronList['moduleName=admin&methodName=deleteLog'] = '删除过期日志';
|
||||
$lang->install->cronList['moduleName=todo&methodName=createCycle'] = '生成周期性待办';
|
||||
$lang->install->cronList['moduleName=ci&methodName=buildTodayJob'] = '创建周期性任务';
|
||||
$lang->install->cronList['moduleName=ci&methodName=checkBuildStatus'] = '同步Jenkins任务状态';
|
||||
$lang->install->cronList['moduleName=ci&methodName=exec'] = '执行Jenkins任务';
|
||||
|
||||
$lang->install->success = "安装成功";
|
||||
$lang->install->login = '登录禅道管理系统';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
$config->integration = new stdclass();
|
||||
$config->integration->create = new stdclass();
|
||||
$config->integration->edit = new stdclass();
|
||||
$config->integration->create->requiredFields = 'name,repo,jenkins,jenkinsJob,triggerType';
|
||||
$config->integration->edit->requiredFields = 'name,repo,jenkins,jenkinsJob,triggerType';
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* The control file of integration of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package integration
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class integration extends control
|
||||
{
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
parent::__construct($moduleName, $methodName);
|
||||
$this->loadModel('ci')->setMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse ci job.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->app->loadLang('compile');
|
||||
$this->view->jobList = $this->integration->getList($orderBy, $pager);
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->integration->browse;
|
||||
$this->view->position[] = $this->lang->ci->job;
|
||||
$this->view->position[] = $this->lang->integration->browse;
|
||||
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->pager = $pager;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ci job.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$this->integration->create();
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->integration->create;
|
||||
$this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
|
||||
$this->view->position[] = $this->lang->integration->create;
|
||||
|
||||
$repoList = $this->loadModel('repo')->getList();
|
||||
$repoPairs = array(0 => '');
|
||||
$repoTypes = array();
|
||||
foreach($repoList as $repo)
|
||||
{
|
||||
$repoPairs[$repo->id] = $repo->name;
|
||||
$repoTypes[$repo->id] = $repo->SCM;
|
||||
}
|
||||
$this->view->repoPairs = $repoPairs;
|
||||
$this->view->repoTypes = $repoTypes;
|
||||
$this->view->jenkinsList = $this->loadModel('jenkins')->getPairs();
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a ci job.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$job = $this->integration->getByID($id);
|
||||
if($_POST)
|
||||
{
|
||||
$this->integration->update($id);
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->integration->edit;
|
||||
$this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
|
||||
$this->view->position[] = $this->lang->integration->edit;
|
||||
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->repo);
|
||||
$repoList = $this->repo->getList();
|
||||
$repoPairs = array(0 => '', $repo->id => $repo->name);
|
||||
$repoTypes[$repo->id] = $repo->SCM;
|
||||
foreach($repoList as $repo)
|
||||
{
|
||||
$repoPairs[$repo->id] = $repo->name;
|
||||
$repoTypes[$repo->id] = $repo->SCM;
|
||||
}
|
||||
|
||||
$this->view->repoPairs = $repoPairs;
|
||||
$this->view->repoTypes = $repoTypes;
|
||||
$this->view->job = $job;
|
||||
$this->view->jenkinsList = $this->loadModel('jenkins')->getPairs();
|
||||
$this->view->jenkinsJobs = $this->jenkins->getTasks($job->jenkins);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a ci job.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id, $confirm = 'no')
|
||||
{
|
||||
if($confirm != 'yes') die(js::confirm($this->lang->integration->confirmDelete, inlink('delete', "jobID=$id&confirm=yes")));
|
||||
|
||||
$this->integration->delete(TABLE_INTEGRATION, $id);
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec a ci job.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function exec($id)
|
||||
{
|
||||
$result = $this->integration->exec($id);
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
if(!$result) $this->send(array('result' => 'fail', 'message' => 'not found'));
|
||||
|
||||
$this->send(array('result' => 'success'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.row.text-with-input .col{line-height: 32px;}
|
||||
.only-pick-time thead th, .only-pick-time tfoot th {color: transparent !important;}
|
||||
.checkbox-primary.checkbox-inline{display:inline-block !important;}
|
||||
.checkbox-primary.checkbox-inline label{padding-left:5px !important;}
|
||||
@@ -0,0 +1,4 @@
|
||||
.row.text-with-input .col {line-height: 32px;}
|
||||
.only-pick-time thead th, .only-pick-time tfoot th {color: transparent !important;}
|
||||
.checkbox-primary.checkbox-inline{display:inline-block !important;}
|
||||
.checkbox-primary.checkbox-inline label{padding-left:5px !important;}
|
||||
@@ -0,0 +1,106 @@
|
||||
$('#repo').change(function()
|
||||
{
|
||||
var repoID = $(this).val();
|
||||
var type = 'Git';
|
||||
if(typeof(repoTypes[repoID]) != 'undefined') type = repoTypes[repoID];
|
||||
$('.svn-fields').toggleClass('hidden', type != 'Subversion');
|
||||
$('#repoType').val(type);
|
||||
if(type == 'Subversion')
|
||||
{
|
||||
$('#svnFolderBox').html("<div class='load-indicator loading'></div>");
|
||||
$.getJSON(createLink('repo', 'ajaxGetSVNTags', 'repoID=' + repoID), function(svnTags)
|
||||
{
|
||||
var tags = svnTags['tags'];
|
||||
var parents = svnTags['parent'];
|
||||
|
||||
html = "<select id='svnFolder' name='svnFolder' class='form-control'>";
|
||||
for(tag in parents)
|
||||
{
|
||||
var info = parents[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
|
||||
for(tag in tags)
|
||||
{
|
||||
var info = tags[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#svnFolderBox').html(html);
|
||||
$('#svnFolderBox #svnFolder').chosen();
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$(document).on('change', '#svnFolder', function()
|
||||
{
|
||||
var repoID = $('#repo').val();
|
||||
var selectedTag = $(this).val();
|
||||
var encodePath = $(this).find("option:selected").attr('data-encodePath');
|
||||
$('#svnFolderBox').html("<div class='load-indicator loading'></div>");
|
||||
$.getJSON(createLink('repo', 'ajaxGetSVNTags', 'repoID=' + repoID + '&path=' + encodePath), function(svnTags)
|
||||
{
|
||||
var tags = svnTags['tags'];
|
||||
var parents = svnTags['parent'];
|
||||
|
||||
html = "<select id='svnFolder' name='svnFolder' class='form-control'>";
|
||||
for(tag in parents)
|
||||
{
|
||||
var info = parents[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
|
||||
for(tag in tags)
|
||||
{
|
||||
var info = tags[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#svnFolderBox').html(html);
|
||||
$('#svnFolderBox #svnFolder').val(selectedTag).chosen();
|
||||
})
|
||||
})
|
||||
|
||||
$('#triggerType').change(function()
|
||||
{
|
||||
var type = $(this).val();
|
||||
if(type == 'tag')
|
||||
{
|
||||
$('.comment-fields').addClass('hidden');
|
||||
$('.custom-fields').addClass('hidden');
|
||||
}
|
||||
else if(type == 'commit')
|
||||
{
|
||||
$('.comment-fields').removeClass('hidden');
|
||||
$('.custom-fields').addClass('hidden');
|
||||
}
|
||||
else if(type == 'schedule')
|
||||
{
|
||||
$('.comment-fields').addClass('hidden');
|
||||
$('.custom-fields').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
$('#jenkins').change(function()
|
||||
{
|
||||
var jenkinsID = $(this).val();
|
||||
$('#jenkinsJobBox').html("<div class='load-indicator loading'></div>");
|
||||
$.getJSON(createLink('jenkins', 'ajaxGetTasks', 'jenkinsID=' + jenkinsID), function(tasks)
|
||||
{
|
||||
html = "<select id='jenkinsJob' name='jenkinsJob' class='form-control'>";
|
||||
for(taskKey in tasks)
|
||||
{
|
||||
var task = tasks[taskKey];
|
||||
html += "<option value='" + taskKey + "'>" + task + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#jenkinsJobBox').html(html);
|
||||
$('#jenkinsJobBox #jenkinsJob').chosen();
|
||||
})
|
||||
})
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#repo').change();
|
||||
$('#triggerType').change();
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
$('#repo').change(function()
|
||||
{
|
||||
var repoID = $(this).val();
|
||||
var type = 'Git';
|
||||
if(typeof(repoTypes[repoID]) != 'undefined') type = repoTypes[repoID];
|
||||
$('.svn-fields').toggleClass('hidden', type != 'Subversion');
|
||||
$('#repoType').val(type);
|
||||
if(type == 'Subversion')
|
||||
{
|
||||
$('#svnFolderBox').html("<div class='load-indicator loading'></div>");
|
||||
var params = 'repoID=' + repoID;
|
||||
if(jobRepo == repoID) params = 'repoID=' + repoID + '&path=' + encodeSVNFolder;
|
||||
$.getJSON(createLink('repo', 'ajaxGetSVNTags', params), function(svnTags)
|
||||
{
|
||||
var tags = svnTags['tags'];
|
||||
var parents = svnTags['parent'];
|
||||
|
||||
html = "<select id='svnFolder' name='svnFolder' class='form-control'>";
|
||||
for(tag in parents)
|
||||
{
|
||||
var info = parents[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
|
||||
for(tag in tags)
|
||||
{
|
||||
var info = tags[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#svnFolderBox').html(html);
|
||||
$('#svnFolderBox #svnFolder').val(svnFolder).chosen();
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$(document).on('change', '#svnFolder', function()
|
||||
{
|
||||
var repoID = $('#repo').val();
|
||||
var selectedTag = $(this).val();
|
||||
var encodePath = $(this).find("option:selected").attr('data-encodePath');
|
||||
$('#svnFolderBox').html("<div class='load-indicator loading'></div>");
|
||||
$.getJSON(createLink('repo', 'ajaxGetSVNTags', 'repoID=' + repoID + '&path=' + encodePath), function(svnTags)
|
||||
{
|
||||
var tags = svnTags['tags'];
|
||||
var parents = svnTags['parent'];
|
||||
|
||||
html = "<select id='svnFolder' name='svnFolder' class='form-control'>";
|
||||
for(tag in parents)
|
||||
{
|
||||
var info = parents[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
|
||||
for(tag in tags)
|
||||
{
|
||||
var info = tags[tag];
|
||||
html += "<option value='" + info['path'] + "' data-encodePath='" + info['encodePath'] + "'>" + info['path'] + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#svnFolderBox').html(html);
|
||||
$('#svnFolderBox #svnFolder').val(selectedTag).chosen();
|
||||
})
|
||||
})
|
||||
|
||||
$('#triggerType').change(function()
|
||||
{
|
||||
var type = $(this).val();
|
||||
if(type == 'tag')
|
||||
{
|
||||
$('.comment-fields').addClass('hidden');
|
||||
$('.custom-fields').addClass('hidden');
|
||||
}
|
||||
else if(type == 'commit')
|
||||
{
|
||||
$('.comment-fields').removeClass('hidden');
|
||||
$('.custom-fields').addClass('hidden');
|
||||
}
|
||||
else if(type == 'schedule')
|
||||
{
|
||||
$('.comment-fields').addClass('hidden');
|
||||
$('.custom-fields').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
$('#jenkins').change(function()
|
||||
{
|
||||
var jenkinsID = $(this).val();
|
||||
$('#jenkinsJobBox').html("<div class='load-indicator loading'></div>");
|
||||
$.getJSON(createLink('jenkins', 'ajaxGetTasks', 'jenkinsID=' + jenkinsID), function(tasks)
|
||||
{
|
||||
html = "<select id='jenkinsJob' name='jenkinsJob' class='form-control'>";
|
||||
for(taskKey in tasks)
|
||||
{
|
||||
var task = tasks[taskKey];
|
||||
html += "<option value='" + taskKey + "'>" + task + "</option>";
|
||||
}
|
||||
html += '</select>';
|
||||
$('#jenkinsJobBox').html(html);
|
||||
$('#jenkinsJobBox #jenkinsJob').chosen();
|
||||
})
|
||||
})
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#repo').change();
|
||||
$('#triggerType').change();
|
||||
});
|
||||
|
||||
function execJob(id)
|
||||
{
|
||||
$.ajax(
|
||||
{
|
||||
type: "POST",
|
||||
url: createLink('integration', 'exec', 'id=' + id),
|
||||
data: {},
|
||||
datatype: "json",
|
||||
success: function(data)
|
||||
{
|
||||
$('.exe-job-button').tooltip('show', sendExec);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
$lang->integration->browse = 'Browse Integration';
|
||||
$lang->integration->create = 'Create Integration';
|
||||
$lang->integration->edit = 'Edit Integration';
|
||||
$lang->integration->execNow = 'Execute now';
|
||||
$lang->integration->delete = 'Delete Integration';
|
||||
$lang->integration->confirmDelete = 'Do you want to delete this Build?';
|
||||
|
||||
$lang->integration->id = 'ID';
|
||||
$lang->integration->name = 'Name';
|
||||
$lang->integration->repo = 'Repo';
|
||||
$lang->integration->svnFolder = 'SVN Tag Watch Path';
|
||||
$lang->integration->jenkins = 'Jenkins Server';
|
||||
$lang->integration->buildType = 'Build Type';
|
||||
$lang->integration->jenkinsJob = 'Jenkins Task';
|
||||
$lang->integration->triggerType = 'Trigger';
|
||||
$lang->integration->scheduleDay = 'Custom Days';
|
||||
$lang->integration->lastExec = 'Last Executed';
|
||||
|
||||
$lang->integration->example = 'e.g.';
|
||||
$lang->integration->commitEx = '%build% %integration% %id%15, to build Jenkins job that id is 15.';
|
||||
$lang->integration->cronSample = 'e.g. 0 0 2 * * 2-6/1 means 2:00 a.m. every weekday.';
|
||||
$lang->integration->sendExec = 'Send execute request success.';
|
||||
|
||||
$lang->integration->buildTypeList['build'] = 'Only Build';
|
||||
$lang->integration->buildTypeList['buildAndDeploy'] = 'Build And Deploy';
|
||||
$lang->integration->buildTypeList['buildAndTest'] = 'Build And Test';
|
||||
|
||||
$lang->integration->triggerTypeList['tag'] = 'Tag';
|
||||
$lang->integration->triggerTypeList['commit'] = 'Code Commit';
|
||||
$lang->integration->triggerTypeList['schedule'] = 'Schedule';
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
$lang->integration->common = '构建任务';
|
||||
$lang->integration->browse = '浏览构建任务';
|
||||
$lang->integration->create = '创建构建任务';
|
||||
$lang->integration->start = '执行构建';
|
||||
$lang->integration->edit = '编辑构建任务';
|
||||
$lang->integration->execNow = '立即执行';
|
||||
$lang->integration->delete = '删除构建任务';
|
||||
$lang->integration->confirmDelete = '确认删除该构建任务吗?';
|
||||
|
||||
$lang->integration->id = 'ID';
|
||||
$lang->integration->name = '名称';
|
||||
$lang->integration->repo = '代码库';
|
||||
$lang->integration->svnFolder = 'SVN Tag监控路径';
|
||||
$lang->integration->jenkins = 'Jenkins服务';
|
||||
$lang->integration->buildType = '构建类型';
|
||||
$lang->integration->jenkinsJob = 'Jenkins任务名';
|
||||
$lang->integration->triggerType = '触发方式';
|
||||
$lang->integration->scheduleDay = '自定义天数';
|
||||
$lang->integration->lastExec = '最后执行';
|
||||
|
||||
$lang->integration->example = '举例';
|
||||
$lang->integration->commitEx = '%build% %integration% %id%15,其中15为Jenkins任务编号';
|
||||
$lang->integration->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点';
|
||||
$lang->integration->sendExec = '发送执行请求成功!';
|
||||
|
||||
$lang->integration->buildTypeList['build'] = '仅构建';
|
||||
$lang->integration->buildTypeList['buildAndDeploy'] = '构建部署';
|
||||
$lang->integration->buildTypeList['buildAndTest'] = '构建测试';
|
||||
|
||||
$lang->integration->triggerTypeList['tag'] = '打标签';
|
||||
$lang->integration->triggerTypeList['commit'] = '代码提交注释';
|
||||
$lang->integration->triggerTypeList['schedule'] = '定时计划';
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* The model file of integration module of ZenTaoCMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Yidong Wang <yidong@cnezsoft.com>
|
||||
* @package integration
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class integrationModel extends model
|
||||
{
|
||||
/**
|
||||
* Get by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getByID($id)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_INTEGRATION)->where('id')->eq($id)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get integration list.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getList($orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
return $this->dao->select('t1.*, t2.name as repoName, t3.name as jenkinsName')->from(TABLE_INTEGRATION)->alias('t1')
|
||||
->leftJoin(TABLE_REPO)->alias('t2')->on('t1.repo=t2.id')
|
||||
->leftJoin(TABLE_JENKINS)->alias('t3')->on('t1.jenkins=t3.id')
|
||||
->where('t1.deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list by triggerType field
|
||||
*
|
||||
* @param string $triggerType
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getListByTriggerType($triggerType)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_INTEGRATION)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('triggerType')->eq($triggerType)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create integration
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$integration = fixer::input('post')
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->remove('repoType')
|
||||
->get();
|
||||
if($integration->triggerType == 'schedule')
|
||||
{
|
||||
if(!isset($integration->scheduleDay)) $integration->scheduleDay = array();
|
||||
$integration->scheduleDay = join(',', $integration->scheduleDay);
|
||||
}
|
||||
else
|
||||
{
|
||||
$integration->scheduleDay = '';
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_INTEGRATION)->data($integration)
|
||||
->batchCheck($this->config->integration->create->requiredFields, 'notempty')
|
||||
|
||||
->batchCheckIF($integration->triggerType === 'schedule', "scheduleDay", 'notempty')
|
||||
->batchCheckIF($this->post->repoType == 'Subversion', "svnFolder", 'notempty')
|
||||
|
||||
->autoCheck()
|
||||
->exec();
|
||||
|
||||
if($integration->triggerType == 'schedule' and strpos($integration->scheduleDay, date('w')) !== false) $this->loadModel('compile')->createByIntegration($integration->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update integration
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$oldIntegration = $this->getById($id);
|
||||
$integration = fixer::input('post')
|
||||
->add('editedBy', $this->app->user->account)
|
||||
->add('editedDate', helper::now())
|
||||
->remove('repoType')
|
||||
->get();
|
||||
if($integration->triggerType == 'schedule')
|
||||
{
|
||||
if(!isset($integration->scheduleDay)) $integration->scheduleDay = array();
|
||||
$integration->scheduleDay = join(',', $integration->scheduleDay);
|
||||
}
|
||||
else
|
||||
{
|
||||
$integration->scheduleDay = '';
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_INTEGRATION)->data($integration)
|
||||
->batchCheck($this->config->integration->edit->requiredFields, 'notempty')
|
||||
|
||||
->batchCheckIF($integration->triggerType === 'schedule', "scheduleDay", 'notempty')
|
||||
->batchCheckIF($this->post->repoType == 'Subversion', "svnFolder", 'notempty')
|
||||
|
||||
->autoCheck()
|
||||
->where('id')->eq($id)
|
||||
->exec();
|
||||
|
||||
if($integration->triggerType == 'schedule')
|
||||
{
|
||||
$week = date('w');
|
||||
if($integration->triggerType != $oldIntegration->triggerType or strpos($oldIntegration->scheduleDay, $week) === false)
|
||||
{
|
||||
if(strpos($integration->scheduleDay, $week) !== false) $this->loadModel('compile')->createByIntegration($integration->id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* The browse view file of ci job module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package ci
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php echo html::a($this->createLink('integration', 'browse'), "<span class='text'>{$lang->ci->task}</span>", '', "class='btn btn-link btn-active-text'");?>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php if(common::hasPriv('integration', 'create')) common::printLink('integration', 'create', "", "<i class='icon icon-plus'></i> " . $lang->integration->create, '', "class='btn btn-primary'");?>
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent'>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='jobList' class='table has-sort-head table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
|
||||
<th class='w-60px'><?php common::printOrderLink('id', $orderBy, $vars, $lang->integration->id);?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->integration->name);?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('repo', $orderBy, $vars, $lang->integration->repo);?></th>
|
||||
<th class='w-150px text-left'><?php echo $lang->integration->triggerType;?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('jenkins', $orderBy, $vars, $lang->integration->jenkins);?></th>
|
||||
<th class='w-200px text-left'><?php echo $lang->integration->jenkinsJob;?></th>
|
||||
<th class='text-left'><?php echo $lang->integration->lastExec;?></th>
|
||||
<th class='w-120px c-actions-4'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($jobList as $id => $job):?>
|
||||
<tr>
|
||||
<td class='text-center'><?php echo $id; ?></td>
|
||||
<td class='text' title='<?php echo $job->name; ?>'><?php echo $job->name; ?></td>
|
||||
<td class='text' title='<?php echo $job->repoName; ?>'><?php echo $job->repoName; ?></td>
|
||||
<?php $triggerType = zget($lang->integration->triggerTypeList, $job->triggerType);?>
|
||||
<td class='text' title='<?php echo $triggerType;?>'><?php echo $triggerType;?></td>
|
||||
<td class='text' title='<?php echo $job->jenkinsName; ?>'><?php echo $job->jenkinsName; ?></td>
|
||||
<td class='text' title='<?php echo $job->jenkinsJob; ?>'><?php echo urldecode($job->jenkinsJob);?></td>
|
||||
<td class='text'><?php if($job->lastStatus) echo zget($lang->compile->statusList, $job->lastStatus) . $lang->ci->at . $job->lastExec;?></td>
|
||||
<td class='c-actions text-center'>
|
||||
<?php
|
||||
common::printIcon('compile', 'browse', "jobID=$id", '', 'list', 'file-text');
|
||||
common::printIcon('integration', 'edit', "jobID=$id", '', 'list', 'edit');
|
||||
if(common::hasPriv('integration', 'delete')) echo html::a($this->createLink('integration', 'delete', "jobID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->integration->delete}' class='btn'");
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($jobList):?>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
<?php endif;?>
|
||||
</form>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* The create view file of integration module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package integration
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
|
||||
<?php js::set('repoTypes', $repoTypes)?>
|
||||
<?php js::set('triggerType', 'tag')?>
|
||||
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->integration->create; ?></h2>
|
||||
</div>
|
||||
<form id='jobForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', '', "class='form-control'"); ?></td>
|
||||
<td colspan="2" ></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->repo; ?></th>
|
||||
<td><?php echo html::select('repo', $repoPairs, '', "class='form-control chosen'"); ?></td>
|
||||
<th class="svn-fields hidden"><?php echo $lang->integration->svnFolder; ?></th>
|
||||
<td class="svn-fields hidden" id='svnFolderBox'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->jenkins; ?></th>
|
||||
<td><?php echo html::select('jenkins', $jenkinsList, '', "class='form-control chosen'"); ?></td>
|
||||
<th><?php echo $lang->integration->jenkinsJob; ?></th>
|
||||
<td id='jenkinsJobBox'><?php echo html::select('jenkinsJob', array('' => ''), '', "class='form-control chosen'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->triggerType; ?></th>
|
||||
<td><?php echo html::select('triggerType', $lang->integration->triggerTypeList, '', "class='form-control chosen'");?></td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
<tr class="comment-fields" class="comment-fields">
|
||||
<th><?php echo $lang->integration->example; ?></th>
|
||||
<?php if(is_string($config->repo->matchComment)) $config->repo->matchComment = json_decode($config->repo->matchComment, true);?>
|
||||
<td colspan="3"><?php echo str_replace(array('%build%', '%integration%', '%id%'), array($config->repo->matchComment['integration']['start'], $config->repo->matchComment['module']['integration'], $config->repo->matchComment['id']['mark']), $lang->integration->commitEx);?></td>
|
||||
</tr>
|
||||
<tr class="custom-fields">
|
||||
<th><?php echo $lang->integration->scheduleDay; ?></th>
|
||||
<td colspan="3"><?php echo html::checkbox('scheduleDay', $lang->datepicker->dayNames, '', '', 'inline');?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton(); ?>
|
||||
<?php echo html::hidden('repoType');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* The edit view file of integration module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package integration
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
|
||||
<?php js::set('repoTypes', $repoTypes)?>
|
||||
<?php js::set('triggerType', $job->triggerType);?>
|
||||
<?php js::set('jobRepo', $job->repo);?>
|
||||
<?php js::set('svnFolder', $job->svnFolder);?>
|
||||
<?php js::set('encodeSVNFolder', $this->loadModel('repo')->encodePath($job->svnFolder));?>
|
||||
<?php js::set('jenkinsJob', $job->jenkinsJob);?>
|
||||
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->integration->edit; ?></h2>
|
||||
</div>
|
||||
<form id='jobForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', $job->name, "class='form-control'"); ?></td>
|
||||
<td colspan="2" ></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->repo; ?></th>
|
||||
<td><?php echo html::select('repo', $repoPairs, $job->repo, "class='form-control chosen'"); ?></td>
|
||||
<th class="svn-fields hidden"><?php echo $lang->integration->svnFolder; ?></th>
|
||||
<td class="svn-fields hidden" id='svnFolderBox'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->jenkins; ?></th>
|
||||
<td><?php echo html::select('jenkins', $jenkinsList, $job->jenkins, "class='form-control chosen'"); ?></td>
|
||||
<th><?php echo $lang->integration->jenkinsJob; ?></th>
|
||||
<td id='jenkinsJobBox'><?php echo html::select('jenkinsJob', $jenkinsJobs, $job->jenkinsJob, "class='form-control chosen'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->integration->triggerType; ?></th>
|
||||
<td><?php echo html::select('triggerType', $lang->integration->triggerTypeList, $job->triggerType, "class='form-control chosen'"); ?></td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
<tr class="comment-fields">
|
||||
<th><?php echo $lang->integration->example; ?></th>
|
||||
<?php if(is_string($config->repo->matchComment)) $config->repo->matchComment = json_decode($config->repo->matchComment, true);?>
|
||||
<td colspan="3"><?php echo str_replace(array('%build%', '%integration%', '%id%'), array($config->repo->matchComment['integration']['start'], $config->repo->matchComment['module']['integration'], $config->repo->matchComment['id']['mark']), $lang->integration->commitEx);?></td>
|
||||
</tr>
|
||||
<tr class="custom-fields">
|
||||
<th><?php echo $lang->integration->scheduleDay;?></th>
|
||||
<td colspan="3"><?php echo html::checkbox('scheduleDay', $lang->datepicker->dayNames, $job->scheduleDay, '', 'inline');?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td colspan="2" class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton(); ?>
|
||||
<?php echo html::hidden('repoType', zget($repoTypes, $job->repo, 'Git'));?>
|
||||
<?php echo html::commonButton($lang->integration->execNow, "onclick=execJob($job->id) data-tip-class='tooltip-success'", "btn btn-info exe-job-button");?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php js::set('sendExec', $lang->integration->sendExec);?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$config->jenkins->create = new stdclass();
|
||||
$config->jenkins->edit = new stdclass();
|
||||
$config->jenkins->create->requiredFields = 'name,serviceUrl,credentials';
|
||||
$config->jenkins->edit->requiredFields = 'name,serviceUrl,credentials';
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The control file of jenkins module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package product
|
||||
* @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class jenkins extends control
|
||||
{
|
||||
/**
|
||||
* jenkins constructor.
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
parent::__construct($moduleName, $methodName);
|
||||
$this->loadModel('ci')->setMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse jenkinss.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
if(common::hasPriv('jenkins', 'create')) $this->lang->modulePageActions = html::a(helper::createLink('jenkins', 'create'), "<i class='icon icon-plus'></i> " . $this->lang->jenkins->create, '', "class='btn btn-primary'");
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->view->title = $this->lang->jenkins->common . $this->lang->colon . $this->lang->jenkins->browse;
|
||||
$this->view->position[] = $this->lang->jenkins->common;
|
||||
$this->view->position[] = $this->lang->jenkins->browse;
|
||||
|
||||
$this->view->jenkinsList = $this->jenkins->getList($orderBy, $pager);
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->pager = $pager;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a jenkins.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$this->jenkins->create();
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$this->view->title = $this->lang->jenkins->common . $this->lang->colon . $this->lang->jenkins->create;
|
||||
$this->view->position[] = html::a(inlink('browse'), $this->lang->jenkins->common);
|
||||
$this->view->position[] = $this->lang->jenkins->create;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a jenkins.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$jenkins = $this->jenkins->getByID($id);
|
||||
if($_POST)
|
||||
{
|
||||
$this->jenkins->update($id);
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$this->view->title = $this->lang->jenkins->common . $this->lang->colon . $this->lang->jenkins->edit;
|
||||
$this->view->position[] = html::a(inlink('browse'), $this->lang->jenkins->common);
|
||||
$this->view->position[] = $this->lang->jenkins->edit;
|
||||
|
||||
$this->view->jenkins = $jenkins;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a jenkins.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id, $confim = 'no')
|
||||
{
|
||||
if($confim != 'yes') die(js::confirm($this->lang->jenkins->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
|
||||
|
||||
$this->jenkins->delete(TABLE_JENKINS, $id);
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get tasks.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetTasks($id)
|
||||
{
|
||||
$tasks = $this->jenkins->getTasks($id);
|
||||
die(json_encode($tasks));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
$lang->jenkins->common = 'Jenkins';
|
||||
$lang->jenkins->browse = 'View';
|
||||
$lang->jenkins->create = 'Create';
|
||||
$lang->jenkins->edit = 'Edit';
|
||||
$lang->jenkins->delete = 'Delete';
|
||||
$lang->jenkins->confirmDelete = 'Do you want to delete this Jenkins server?';
|
||||
|
||||
$lang->jenkins->id = 'ID';
|
||||
$lang->jenkins->name = 'Name';
|
||||
$lang->jenkins->serviceUrl = 'Service URL';
|
||||
$lang->jenkins->token = 'Token';
|
||||
$lang->jenkins->account = 'UserName';
|
||||
$lang->jenkins->password = 'Password';
|
||||
|
||||
$lang->jenkins->desc = 'Description';
|
||||
$lang->jenkins->tokenFirst = 'Use token if not empty.';
|
||||
$lang->jenkins->tips = 'Cancel "Prevent Cross Site Request Forgery exploits" when using password.';
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
$lang->jenkins->common = 'Jenkins';
|
||||
$lang->jenkins->browse = '浏览';
|
||||
$lang->jenkins->create = '创建';
|
||||
$lang->jenkins->edit = '编辑';
|
||||
$lang->jenkins->delete = '删除';
|
||||
$lang->jenkins->confirmDelete = '确认删除该Jenkins吗?';
|
||||
|
||||
$lang->jenkins->id = 'ID';
|
||||
$lang->jenkins->name = '名称';
|
||||
$lang->jenkins->serviceUrl = '服务地址';
|
||||
$lang->jenkins->token = 'Token';
|
||||
$lang->jenkins->account = '用户名';
|
||||
$lang->jenkins->password = '密码';
|
||||
|
||||
$lang->jenkins->desc = '描述';
|
||||
$lang->jenkins->tokenFirst = 'Token不为空时,优先使用Token。';
|
||||
$lang->jenkins->tips = '使用密码时,请在Jenkins全局安全设置中禁用"防止跨站点请求伪造"选项。';
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* The model file of jenkins module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chenqi <chenqi@cnezsoft.com>
|
||||
* @package product
|
||||
* @version $Id: $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
|
||||
class jenkinsModel extends model
|
||||
{
|
||||
/**
|
||||
* Get a jenkins by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getByID($id)
|
||||
{
|
||||
$jenkins = $this->dao->select('*')->from(TABLE_JENKINS)->where('id')->eq($id)->fetch();
|
||||
$jenkins->password = base64_decode($jenkins->password);
|
||||
|
||||
return $jenkins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jenkins list.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getList($orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_JENKINS)
|
||||
->where('deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a jenkins.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$jenkins = fixer::input('post')
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->skipSpecial('serviceUrl,token,account,password')
|
||||
->get();
|
||||
|
||||
$jenkins->password = base64_encode($jenkins->password);
|
||||
|
||||
$this->dao->insert(TABLE_JENKINS)->data($jenkins)
|
||||
->batchCheck($this->config->jenkins->create->requiredFields, 'notempty')
|
||||
->batchCheck("serviceUrl", 'URL')
|
||||
->autoCheck()
|
||||
->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a jenkins.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$jenkins = fixer::input('post')
|
||||
->add('editedBy', $this->app->user->account)
|
||||
->add('editedDate', helper::now())
|
||||
->skipSpecial('serviceUrl,token,account,password')
|
||||
->get();
|
||||
|
||||
$jenkins->password = base64_encode($jenkins->password);
|
||||
|
||||
$this->dao->update(TABLE_JENKINS)->data($jenkins)
|
||||
->batchCheck($this->config->jenkins->edit->requiredFields, 'notempty')
|
||||
->batchCheck("serviceUrl", 'URL')
|
||||
->autoCheck()
|
||||
->where('id')->eq($id)
|
||||
->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* list jenkins for ci task edit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPairs()
|
||||
{
|
||||
$jenkins = $this->dao->select('id,name')->from(TABLE_JENKINS)->where('deleted')->eq('0')->orderBy('id')->fetchPairs('id', 'name');
|
||||
$jenkins = array('' => '') + $jenkins;
|
||||
return $jenkins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jenkins tasks.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTasks($id)
|
||||
{
|
||||
$jenkins = $this->getById($id);
|
||||
|
||||
$jenkinsServer = $jenkins->serviceUrl;
|
||||
$jenkinsUser = $jenkins->account;
|
||||
$jenkinsPassword = $jenkins->token ? $jenkins->token : $jenkins->password;
|
||||
|
||||
$jenkinsAuth = '://' . $jenkinsUser . ':' . $jenkinsPassword . '@';
|
||||
$jenkinsServer = str_replace('://', $jenkinsAuth, $jenkinsServer);
|
||||
|
||||
$response = common::http($jenkinsServer . '/api/json/items/list');
|
||||
$response = json_decode($response);
|
||||
|
||||
$tasks = array();
|
||||
if(isset($response->jobs))
|
||||
{
|
||||
foreach($response->jobs as $job) $tasks[basename($job->url)] = $job->name;
|
||||
}
|
||||
return $tasks;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* The browse view file of jenkins module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package jenkins
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='jenkinsList' class='table has-sort-head table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; ?>
|
||||
<th class='w-60px'><?php common::printOrderLink('id', $orderBy, $vars, $lang->jenkins->id); ?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->jenkins->name); ?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('serviceUrl', $orderBy, $vars, $lang->jenkins->serviceUrl); ?></th>
|
||||
<th class='w-100px c-actions-4'><?php echo $lang->actions; ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($jenkinsList as $id => $jenkins): ?>
|
||||
<tr>
|
||||
<td class='text-center'><?php echo $id; ?></td>
|
||||
<td class='text' title='<?php echo $jenkins->name; ?>'><?php echo $jenkins->name; ?></td>
|
||||
<td class='text' title='<?php echo $jenkins->serviceUrl; ?>'><?php echo $jenkins->serviceUrl; ?></td>
|
||||
<td class='c-actions text-left'>
|
||||
<?php
|
||||
common::printIcon('jenkins', 'edit', "jenkinsID=$id", '', 'list', 'edit');
|
||||
if(common::hasPriv('jenkins', 'delete')) echo html::a($this->createLink('jenkins', 'delete', "jenkinsID=$id"), '<i class="icon-trash"></i>', '', "title='{$lang->jenkins->delete}' class='btn'");
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($jenkinsList):?>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* The create view file of jenkins module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package jenkins
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->jenkins->create; ?></h2>
|
||||
</div>
|
||||
<form id='jenkinsForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', '', "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->serviceUrl; ?></th>
|
||||
<td class='required'><?php echo html::input('serviceUrl', '', "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->account;?></th>
|
||||
<td><?php echo html::input('account', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->token;?></th>
|
||||
<td><?php echo html::input('token', '', "class='form-control'");?></td>
|
||||
<td><?php echo $lang->jenkins->tokenFirst;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->password;?></th>
|
||||
<td><?php echo html::password('password', '', "class='form-control'");?></td>
|
||||
<td><?php echo $lang->jenkins->tips;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton(); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* The edit view file of jenkins module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package jenkins
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php'; ?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->jenkins->edit; ?></h2>
|
||||
</div>
|
||||
<form id='jenkinsForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='thWidth'></th>
|
||||
<td colspan="2"><?php echo $lang->jenkins->tips; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', $jenkins->name, "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->serviceUrl; ?></th>
|
||||
<td class='required'><?php echo html::input('serviceUrl', $jenkins->serviceUrl, "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->account;?></th>
|
||||
<td><?php echo html::input('account', $jenkins->account, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->token;?></th>
|
||||
<td><?php echo html::input('token', $jenkins->token, "class='form-control'");?></td>
|
||||
<td><?php echo $lang->jenkins->tokenFirst;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->jenkins->password;?></th>
|
||||
<td><?php echo html::password('password', $jenkins->password, "class='form-control'");?></td>
|
||||
<td><?php echo $lang->jenkins->tips;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton() ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -17,7 +17,7 @@
|
||||
$recTotalLabel = " <span class='label label-light label-badge'>{$pager->recTotal}</span>";
|
||||
echo html::a(inlink('bug', "type=assignedTo"), "<span class='text'>{$lang->bug->assignedTo}</span>" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink('bug', "type=openedBy"), "<span class='text'>{$lang->bug->openedByMe}</span>" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink('bug', "type=resolvedBy"), "<span class='text'>{$lang->bug->resolvedBy}</span>" . ($type == 'resolvedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'resolvedBy' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink('bug', "type=resolvedBy"), "<span class='text'>{$lang->bug->resolvedByMe}</span>" . ($type == 'resolvedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'resolvedBy' ? ' btn-active-text' : '') . "'");
|
||||
echo html::a(inlink('bug', "type=closedBy"), "<span class='text'>{$lang->bug->closedByMe}</span>" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'");
|
||||
?>
|
||||
</div>
|
||||
|
||||
@@ -48,12 +48,11 @@
|
||||
<th class='c-project'> <?php common::printOrderLink('project', $orderBy, $vars, $lang->task->project);?></th>
|
||||
<th class='c-name'> <?php common::printOrderLink('name', $orderBy, $vars, $lang->task->name);?></th>
|
||||
<th class='c-user w-90px'><?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-120px c-assignedTo'><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->task->assignedTo);?></th>
|
||||
<th class='w-90px c-assignedTo'><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->task->assignedTo);?></th>
|
||||
<th class='c-user w-100px'><?php common::printOrderLink('finishedBy', $orderBy, $vars, $lang->task->finishedBy);?></th>
|
||||
<th class='c-hours w-70px'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->task->estimateAB);?></th>
|
||||
<th class='c-hours'> <?php common::printOrderLink('consumed', $orderBy, $vars, $lang->task->consumedAB);?></th>
|
||||
<th class='c-hours'> <?php common::printOrderLink('left', $orderBy, $vars, $lang->task->leftAB);?></th>
|
||||
<th class='c-date'> <?php common::printOrderLink('deadline', $orderBy, $vars, $lang->task->deadlineAB);?></th>
|
||||
<th class='c-hours w-50px'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->task->estimateAB);?></th>
|
||||
<th class='c-hours w-50px'> <?php common::printOrderLink('consumed', $orderBy, $vars, $lang->task->consumedAB);?></th>
|
||||
<th class='c-hours w-50px'> <?php common::printOrderLink('left', $orderBy, $vars, $lang->task->leftAB);?></th>
|
||||
<th class='c-status'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='c-actions-6'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
@@ -83,7 +82,6 @@
|
||||
<td class='c-hours'><?php echo $task->estimate;?></td>
|
||||
<td class='c-hours'><?php echo $task->consumed;?></td>
|
||||
<td class='c-hours'><?php echo $task->left;?></td>
|
||||
<td class='c-date <?php if(isset($task->delay)) echo 'text-red';?>'><?php if(substr($task->deadline, 0, 4) > 0) echo $task->deadline;?></td>
|
||||
<td class='c-status'>
|
||||
<?php $storyChanged = (!empty($task->storyStatus) and $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion and !in_array($task->status, array('cancel', 'closed')));?>
|
||||
<?php !empty($storyChanged) ? print("<span class='status-story status-changed'>{$this->lang->story->changed}</span>") : print("<span class='status-task status-{$task->status}'> " . $this->processStatus('task', $task) . "</span>");?>
|
||||
|
||||
@@ -26,3 +26,34 @@ $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->create = array('id' => 'desc', 'tools' => 'simpleTools');
|
||||
$config->repo->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools');
|
||||
$config->repo->editor->view = array('id' => 'commentText', 'tools' => 'simpleTools');
|
||||
$config->repo->editor->diff = array('id' => 'commentText', 'tools' => 'simpleTools');
|
||||
|
||||
$config->repo->create = new stdclass();
|
||||
$config->repo->create->requiredFields = 'SCM,name,path,encoding,client';
|
||||
$config->repo->edit = new stdclass();
|
||||
$config->repo->edit->requiredFields = 'SCM,name,path,encoding,client';
|
||||
$config->repo->svn = new stdclass();
|
||||
$config->repo->svn->requiredFields = 'account,password';
|
||||
|
||||
$config->repo->matchComment['module']['story'] = 'Story';
|
||||
$config->repo->matchComment['module']['task'] = 'Task';
|
||||
$config->repo->matchComment['module']['bug'] = 'Bug';
|
||||
$config->repo->matchComment['module']['integration'] = 'Build';
|
||||
$config->repo->matchComment['task']['start'] = 'Start';
|
||||
$config->repo->matchComment['task']['finish'] = 'Finish';
|
||||
$config->repo->matchComment['task']['cancel'] = 'Cancel';
|
||||
$config->repo->matchComment['task']['consumed'] = 'Cost';
|
||||
$config->repo->matchComment['task']['left'] = 'Left';
|
||||
$config->repo->matchComment['bug']['resolve'] = 'Fix';
|
||||
$config->repo->matchComment['bug']['resolvedBuild'] = 'Build';
|
||||
$config->repo->matchComment['integration']['start'] = 'Start';
|
||||
$config->repo->matchComment['id']['mark'] = '#';
|
||||
$config->repo->matchComment['id']['split'] = ',';
|
||||
$config->repo->matchComment['mark']['consumed'] = ':';
|
||||
$config->repo->matchComment['mark']['left'] = ':';
|
||||
$config->repo->matchComment['mark']['resolvedBuild'] = '#';
|
||||
|
||||
+226
-28
@@ -29,7 +29,6 @@ class repo extends control
|
||||
|
||||
$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'></i> " . $this->lang->repo->create, '', "class='btn btn-primary'");
|
||||
if(empty($this->repos) and $this->methodName != 'create') die(js::locate($this->repo->createLink('create')));
|
||||
|
||||
/* Unlock session for wait to get data of repo. */
|
||||
@@ -37,54 +36,104 @@ class repo extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Create repo.
|
||||
*
|
||||
* List all repo.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function maintain($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$repoID = $this->session->repoID;
|
||||
$this->repo->setMenu($this->repos, $repoID, false);
|
||||
if(common::hasPriv('repo', 'create')) $this->lang->modulePageActions = html::a(helper::createLink('repo', 'create'), "<i class='icon icon-plus'></i> " . $this->lang->repo->create, '', "class='btn btn-primary'");
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->view->repoList = $this->repo->getList($orderBy, $pager);
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->browse;
|
||||
$this->view->position[] = $this->lang->repo->common;
|
||||
$this->view->position[] = $this->lang->repo->browse;
|
||||
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->pager = $pager;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a repo.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->repo->setMenu($this->repos);
|
||||
if(!empty($_POST))
|
||||
if($_POST)
|
||||
{
|
||||
$repoID = $this->repo->create();
|
||||
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
die(js::locate($this->repo->createLink('showSyncComment', "repoID=$repoID"), 'parent'));
|
||||
|
||||
$link = $this->repo->createLink('showSyncComment', "repoID=$repoID");
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->create;
|
||||
$this->repo->setMenu($this->repos, '', false);
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted');
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->create;
|
||||
$this->view->position[] = html::a(inlink('maintain'), $this->lang->repo->common);
|
||||
$this->view->position[] = $this->lang->repo->create;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* Edit a repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function settings($repoID = 0)
|
||||
public function edit($repoID)
|
||||
{
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
if(!empty($_POST))
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
if($_POST)
|
||||
{
|
||||
$needSync = $this->repo->saveSettings($repoID);
|
||||
$noNeedSync = $this->repo->update($repoID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
if(!$needSync)
|
||||
if(!$noNeedSync)
|
||||
{
|
||||
die(js::locate($this->repo->createLink('showSyncComment', "repoID=$repoID"), 'parent'));
|
||||
$link = $this->repo->createLink('showSyncComment', "repoID=$repoID");
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link));
|
||||
}
|
||||
die(js::locate($this->repo->createLink('log', "repoID=$repoID"), 'parent'));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('maintain')));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->repo->settings;
|
||||
$this->view->repo = $this->repo->getRepoByID($repoID);
|
||||
$this->repo->setMenu($this->repos, $repo->id, false);
|
||||
$this->app->loadLang('action');
|
||||
|
||||
$repo->repoType = $repo->id . '-' . $repo->SCM;
|
||||
$this->view->repo = $repo;
|
||||
$this->view->repoID = $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();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted');
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->edit;
|
||||
$this->view->position[] = html::a(inlink('maintain'), $this->lang->repo->common);
|
||||
$this->view->position[] = $this->lang->repo->edit;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,12 +150,14 @@ class repo extends control
|
||||
{
|
||||
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'));
|
||||
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,6 +244,9 @@ class repo extends control
|
||||
$this->view->logType = $logType;
|
||||
$this->view->info = $info;
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->view;
|
||||
$this->view->position[] = $this->lang->repo->common;
|
||||
$this->view->position[] = $this->lang->repo->view;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -302,7 +356,7 @@ class repo extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
$change['view'] = $viewPriv ? html::a($this->repo->createLink('log', "repoID=$repoID&entry=&revision=$revision", "entry=$encodePath"), $this->lang->repo->log) : '';
|
||||
$change['view'] = $viewPriv ? html::a($this->repo->createLink('browse', "repoID=$repoID&path=&revision=$revision", "path=$encodePath"), $this->lang->repo->browse) : '';
|
||||
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;
|
||||
@@ -330,6 +384,55 @@ class repo extends control
|
||||
$this->view->oldRevision = $oldRevision;
|
||||
$this->view->preAndNext = $this->repo->getPreAndNext($repo, $root, $revision, $type, 'revision');
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->viewRevision;
|
||||
$this->view->position[] = $this->lang->repo->common;
|
||||
$this->view->position[] = $this->lang->repo->viewRevision;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame repo file.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function blame($repoID, $entry, $revision = 'HEAD', $encoding = '')
|
||||
{
|
||||
if($this->get->entry) $entry = $this->get->entry;
|
||||
$this->repo->setMenu($this->repos, $repoID);
|
||||
if($repoID == 0) $repoID = $this->session->repoID;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
$file = $entry;
|
||||
$entry = $this->repo->decodePath($entry);
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$encoding = empty($encoding) ? $repo->encoding : $encoding;
|
||||
$encoding = strtolower(str_replace('_', '-', $encoding));
|
||||
$blames = $this->scm->blame($entry, $revision);
|
||||
$revisions = array();
|
||||
foreach($blames as $i => $blame)
|
||||
{
|
||||
if(isset($blame['revision'])) $revisions[$blame['revision']] = $blame['revision'];
|
||||
if($encoding != 'utf-8') $blames[$i]['content'] = helper::convertEncoding($blame['content'], $encoding);
|
||||
}
|
||||
|
||||
$log = $repo->SCM == 'Git' ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch() : '';
|
||||
|
||||
$this->view->title = $this->lang->repo->common;
|
||||
$this->view->repoID = $repoID;
|
||||
$this->view->repo = $repo;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->entry = $entry;
|
||||
$this->view->file = $file;
|
||||
$this->view->encoding = str_replace('-', '_', $encoding);
|
||||
$this->view->historys = $repo->SCM == 'Git' ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($revisions)->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
|
||||
$this->view->revisionName = ($log and $repo->SCM == 'Git') ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $revision;
|
||||
$this->view->blames = $blames;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -420,9 +523,6 @@ class repo extends control
|
||||
}
|
||||
}
|
||||
|
||||
$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);
|
||||
@@ -439,6 +539,10 @@ class repo extends control
|
||||
$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->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->diff;
|
||||
$this->view->position[] = $this->lang->repo->common;
|
||||
$this->view->position[] = $this->lang->repo->diff;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -466,6 +570,37 @@ class repo extends control
|
||||
$this->fetch('file', 'sendDownHeader', array("fileName" => $fileName, "fileType" => $extension, "content" => $content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set matchComment.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMatchComment($module = '')
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$module = $this->post->selectModule;
|
||||
unset($_POST['selectModule']);
|
||||
$this->loadModel('setting')->setItem('system.repo.matchComment', json_encode($this->post->matchComment));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('setMatchComment', "module={$module}")));
|
||||
}
|
||||
|
||||
$this->repo->setMenu($this->repos, $this->session->repoID, false);
|
||||
|
||||
$this->app->loadLang('task');
|
||||
$this->app->loadLang('bug');
|
||||
$this->app->loadLang('story');
|
||||
$this->app->loadLang('integration');
|
||||
if(is_string($this->config->repo->matchComment)) $this->config->repo->matchComment = json_decode($this->config->repo->matchComment, true);
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->setMatchComment;
|
||||
$this->view->position[] = $this->lang->repo->setMatchComment;
|
||||
|
||||
$this->view->selectModule = $module;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show sync comment.
|
||||
*
|
||||
@@ -628,4 +763,67 @@ class repo extends control
|
||||
|
||||
die('norecords');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get svn tags
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetSVNTags($repoID, $path = '', $revision = 'HEAD')
|
||||
{
|
||||
if($this->get->path) $entry = $this->get->path;
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
if($repo->SCM != 'Subversion') die(json_encode(array()));
|
||||
|
||||
$this->scm->setEngine($repo);
|
||||
$path = $this->repo->decodePath($path);
|
||||
$tags = $this->scm->tags($path, $revision);
|
||||
|
||||
$parentInfos = array();
|
||||
$parentPath = '';
|
||||
|
||||
$info = array();
|
||||
$info['path'] = '/';
|
||||
$info['url'] = $repo->path . $info['path'];
|
||||
$info['encodePath'] = $this->repo->encodePath($info['path']);
|
||||
$parentInfos['/'] = $info;
|
||||
|
||||
foreach(explode('/', $path) as $parent)
|
||||
{
|
||||
if(empty($parent)) continue;
|
||||
$parentPath .= '/' . $parent;
|
||||
|
||||
$info = array();
|
||||
$info['path'] = $parentPath;
|
||||
$info['url'] = $repo->path . $info['path'];
|
||||
|
||||
$info['encodePath'] = $this->repo->encodePath($info['path']);
|
||||
|
||||
$parentInfos[$parent] = $info;
|
||||
}
|
||||
|
||||
$tagInfos = array();
|
||||
foreach($tags as $tag)
|
||||
{
|
||||
$info = array();
|
||||
$info['path'] = '/';
|
||||
if($path) $info['path'] .= $path . '/';
|
||||
$info['path'] .= $tag;
|
||||
$info['url'] = $repo->path . $info['path'];
|
||||
|
||||
$info['encodePath'] = $this->repo->encodePath($info['path']);
|
||||
|
||||
$tagInfos[$tag] = $info;
|
||||
}
|
||||
|
||||
$svnTags = array();
|
||||
$svnTags['parent'] = $parentInfos;
|
||||
$svnTags['tags'] = $tagInfos;
|
||||
|
||||
die(json_encode($svnTags));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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;}
|
||||
h2,h3 {font-size:20px; 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')}
|
||||
@@ -76,11 +76,11 @@ h3 {font-size:16px;}
|
||||
.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 > i:before {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.over.commented .comment-btn .icon-wrapper > i:before {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;}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
$(function()
|
||||
{
|
||||
scmChanged(scm);
|
||||
});
|
||||
|
||||
function scmChanged(scm) {
|
||||
if(scm == 'Git')
|
||||
{
|
||||
$('.account-fields').addClass('hidden');
|
||||
|
||||
$('.tips-git').removeClass('hidden');
|
||||
$('.tips-svn').addClass('hidden');
|
||||
} else
|
||||
{
|
||||
$('.account-fields').removeClass('hidden');
|
||||
|
||||
$('.tips-git').addClass('hidden');
|
||||
$('.tips-svn').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
$(function()
|
||||
{
|
||||
scmChanged(scm);
|
||||
});
|
||||
|
||||
function scmChanged(scm) {
|
||||
if(scm == 'Git')
|
||||
{
|
||||
$('.account-fields').addClass('hidden');
|
||||
|
||||
$('.tips-git').removeClass('hidden');
|
||||
$('.tips-svn').addClass('hidden');
|
||||
} else
|
||||
{
|
||||
$('.account-fields').removeClass('hidden');
|
||||
|
||||
$('.tips-git').addClass('hidden');
|
||||
$('.tips-svn').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
<?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';
|
||||
+30
-9
@@ -1,11 +1,15 @@
|
||||
<?php
|
||||
$lang->repo->common = 'Repo';
|
||||
$lang->repo->create = 'Create Repo';
|
||||
$lang->repo->settings = 'Settings';
|
||||
$lang->repo->browse = 'View Repo';
|
||||
$lang->repo->browse = 'View';
|
||||
$lang->repo->viewRevision = 'View Revision';
|
||||
$lang->repo->create = 'Create';
|
||||
$lang->repo->createAction = 'Create Repo';
|
||||
$lang->repo->edit = 'Edit';
|
||||
$lang->repo->editAction = 'Edit Repo';
|
||||
$lang->repo->delete = 'Delete Repo';
|
||||
$lang->repo->showSyncComment = 'Display Synchronization';
|
||||
$lang->repo->ajaxSyncComment = 'Interface: Ajax Sync Note';
|
||||
$lang->repo->setMatchComment = 'Set match comment';
|
||||
$lang->repo->download = 'Download File';
|
||||
$lang->repo->downloadDiff = 'Download Diff';
|
||||
$lang->repo->diffAction = 'Revision Diff';
|
||||
@@ -17,6 +21,7 @@ $lang->repo->deleteBug = 'Delete Bug';
|
||||
$lang->repo->addComment = 'Add Comment';
|
||||
$lang->repo->editComment = 'Edit Comment';
|
||||
$lang->repo->deleteComment = 'Delete Comment';
|
||||
$lang->repo->selectModule = 'Select Module';
|
||||
|
||||
$lang->repo->submit = 'Submit';
|
||||
$lang->repo->cancel = 'Cancel';
|
||||
@@ -40,6 +45,7 @@ $lang->repo->name = 'Name';
|
||||
$lang->repo->path = 'Path';
|
||||
$lang->repo->prefix = 'Prefix';
|
||||
$lang->repo->config = 'Config';
|
||||
$lang->repo->desc = 'Describe';
|
||||
$lang->repo->account = 'Username';
|
||||
$lang->repo->password = 'Password';
|
||||
$lang->repo->encoding = 'Encoding';
|
||||
@@ -90,6 +96,8 @@ $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->mark = "Mark Tag";
|
||||
$lang->repo->split = "Split Mark";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = 'Inline';
|
||||
$lang->repo->viewDiffList['appose'] = 'Parallel';
|
||||
@@ -104,8 +112,8 @@ $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->scmList['Subversion'] = 'Subversion';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = 'Synchronizing. Please wait ...';
|
||||
@@ -118,6 +126,12 @@ $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->matchComment = new stdclass();
|
||||
$lang->repo->matchComment->exampleLabel = "Comment Example";
|
||||
$lang->repo->matchComment->example['task']['start'] = "%start% %task% %id%1%split%2 %cost%%consumedmark%1 %left%%leftmark%3";
|
||||
$lang->repo->matchComment->example['task']['finish'] = "%finish% %task% %id%1%split%2 %cost%%consumedmark%10";
|
||||
$lang->repo->matchComment->example['bug']['resolve'] = "%resolve% %bug% %id%1%split%2 %resolvedBuild% %buildmark%10";
|
||||
|
||||
$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!';
|
||||
@@ -137,11 +151,18 @@ $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->synTips = '<strong>You may find the reference about how to set Git sync from <a target="_blank" href="https://www.zentao.pm/book/zentaomanual/free-open-source-project-management-software-git-105.html">here</a>.</strong>';
|
||||
$lang->repo->encodingsTips = "The encodings of commit comments, can be comma separated values,e.g. utf-8";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = new stdclass();
|
||||
$lang->repo->example->path = new stdclass();
|
||||
$lang->repo->example->client->git = "e.g. /usr/bin/git";
|
||||
$lang->repo->example->client->svn = "e.g. /usr/bin/svn";
|
||||
$lang->repo->example->path->git = "e.g. /homt/user/myproject";
|
||||
$lang->repo->example->path->svn = "e.g. http://example.googlecode.com/svn/trunk/myproject";
|
||||
$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';
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
<?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';
|
||||
@@ -1,11 +1,15 @@
|
||||
<?php
|
||||
$lang->repo->common = '代码';
|
||||
$lang->repo->create = '创建版本库';
|
||||
$lang->repo->settings = '版本库设置';
|
||||
$lang->repo->browse = '浏览';
|
||||
$lang->repo->viewRevision = '查看修订';
|
||||
$lang->repo->create = '创建';
|
||||
$lang->repo->createAction = '创建版本库';
|
||||
$lang->repo->edit = '编辑';
|
||||
$lang->repo->editAction = '编辑版本库';
|
||||
$lang->repo->delete = '删除版本库';
|
||||
$lang->repo->showSyncComment = '显示同步进度';
|
||||
$lang->repo->ajaxSyncComment = '接口:AJAX同步注释';
|
||||
$lang->repo->setMatchComment = '注释指令配置';
|
||||
$lang->repo->download = '下载';
|
||||
$lang->repo->downloadDiff = '下载Diff';
|
||||
$lang->repo->diffAction = '版本对比';
|
||||
@@ -17,6 +21,7 @@ $lang->repo->deleteBug = '删除评审';
|
||||
$lang->repo->addComment = '添加备注';
|
||||
$lang->repo->editComment = '编辑备注';
|
||||
$lang->repo->deleteComment = '删除备注';
|
||||
$lang->repo->selectModule = '选择模块';
|
||||
|
||||
$lang->repo->submit = '提交';
|
||||
$lang->repo->cancel = '取消';
|
||||
@@ -40,6 +45,7 @@ $lang->repo->name = '名称';
|
||||
$lang->repo->path = '地址';
|
||||
$lang->repo->prefix = '地址扩展';
|
||||
$lang->repo->config = '配置目录';
|
||||
$lang->repo->desc = '描述';
|
||||
$lang->repo->account = '用户名';
|
||||
$lang->repo->password = '密码';
|
||||
$lang->repo->encoding = '编码';
|
||||
@@ -90,6 +96,8 @@ $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->mark = "匹配标记";
|
||||
$lang->repo->split = "分割匹配";
|
||||
|
||||
$lang->repo->viewDiffList['inline'] = '直列';
|
||||
$lang->repo->viewDiffList['appose'] = '并排';
|
||||
@@ -104,8 +112,8 @@ $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->scmList['Subversion'] = 'Subversion';
|
||||
|
||||
$lang->repo->notice = new stdclass();
|
||||
$lang->repo->notice->syncing = '正在同步中, 请稍等...';
|
||||
@@ -118,6 +126,14 @@ $lang->repo->notice->deleteBug = '确认删除该Bug?';
|
||||
$lang->repo->notice->deleteComment = '确认删除该回复?';
|
||||
$lang->repo->notice->lastSyncTime = '最后更新于:';
|
||||
|
||||
$lang->repo->matchComment = new stdclass();
|
||||
$lang->repo->matchComment->exampleLabel = "注释示例";
|
||||
$lang->repo->matchComment->example['story']['common'] = "%story% %id%1%split%2";
|
||||
$lang->repo->matchComment->example['task']['start'] = "%start% %task% %id%1%split%2 %cost%%consumedmark%1 %left%%leftmark%3";
|
||||
$lang->repo->matchComment->example['task']['finish'] = "%finish% %task% %id%1%split%2 %cost%%consumedmark%10";
|
||||
$lang->repo->matchComment->example['bug']['resolve'] = "%resolve% %bug% %id%1%split%2 %resolvedBuild% %buildmark%10";
|
||||
$lang->repo->matchComment->example['integration']['start'] = "%build% %integration% %id%1%split%2";
|
||||
|
||||
$lang->repo->error = new stdclass();
|
||||
$lang->repo->error->useless = '你的服务器禁用了exec,shell_exec方法,无法使用该功能';
|
||||
$lang->repo->error->connect = '连接版本库失败,请填写正确的用户名、密码和版本库地址!';
|
||||
@@ -137,11 +153,18 @@ $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->synTips = '请参照<a target="_blank" href="https://www.zentao.net/book/zentaopmshelp/207.html">这里</a>,设置版本库定时同步。';
|
||||
$lang->repo->encodingsTips = "提交日志的编码,可以用逗号连接起来的多个,比如utf-8。";
|
||||
|
||||
$lang->repo->example = new stdclass();
|
||||
$lang->repo->example->client = new stdclass();
|
||||
$lang->repo->example->path = new stdclass();
|
||||
$lang->repo->example->client->git = "例如:/usr/bin/git";
|
||||
$lang->repo->example->client->svn = "例如:/usr/bin/svn";
|
||||
$lang->repo->example->path->git = "例如:/homt/user/myproject";
|
||||
$lang->repo->example->path->svn = "例如:http://example.googlecode.com/svn/trunk/myproject";
|
||||
$lang->repo->example->config = "https需要填写配置目录的位置,通过config-dir选项生成配置目录";
|
||||
$lang->repo->example->encoding = "填写版本库中文件的编码";
|
||||
|
||||
$lang->repo->typeList['standard'] = '规范';
|
||||
$lang->repo->typeList['performance'] = '性能';
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
<?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'] = '邏輯錯誤';
|
||||
+292
-76
@@ -32,7 +32,7 @@ class repoModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMenu($repos, $repoID = '')
|
||||
public function setMenu($repos, $repoID = '', $showRepoSeletion = true)
|
||||
{
|
||||
if(empty($repoID)) $repoID = $this->session->repoID ? $this->session->repoID : key($repos);
|
||||
if(!isset($repos[$repoID])) $repoID = key($repos);
|
||||
@@ -54,7 +54,7 @@ class repoModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($repos))
|
||||
if($showRepoSeletion && !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);
|
||||
@@ -131,14 +131,21 @@ class repoModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all repos.
|
||||
*
|
||||
* Get repo list.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param bool $decode
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getAllRepos()
|
||||
public function getList($orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq(0)->fetchAll();
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
foreach($repos as $i => $repo)
|
||||
{
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
@@ -148,6 +155,109 @@ class repoModel extends model
|
||||
return $repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list by SCM.
|
||||
*
|
||||
* @param strint $scm
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getListBySCM($scm, $type = 'all')
|
||||
{
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0')
|
||||
->andWhere('SCM')->eq($scm)
|
||||
->orderBy('id')
|
||||
->fetchAll();
|
||||
|
||||
foreach($repos as $i => $repo)
|
||||
{
|
||||
if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password);
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
if($type == 'haspriv' and !$this->checkPriv($repo)) unset($repos[$i]);
|
||||
}
|
||||
|
||||
return $repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a repo.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
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)
|
||||
->batchCheck($this->config->repo->create->requiredFields, 'notempty')
|
||||
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
|
||||
->autoCheck()
|
||||
->exec();
|
||||
return $this->dao->lastInsertID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a repo.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$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($id);
|
||||
$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)
|
||||
->batchCheck($this->config->repo->edit->requiredFields, 'notempty')
|
||||
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
|
||||
->autoCheck()
|
||||
->where('id')->eq($id)->exec();
|
||||
|
||||
if($repo->path != $data->path)
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($id)->exec();
|
||||
$this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($id)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repo pairs.
|
||||
*
|
||||
@@ -185,6 +295,25 @@ class repoModel extends model
|
||||
return $repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get by id list.
|
||||
*
|
||||
* @param array $idList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByIdList($idList)
|
||||
{
|
||||
$repos = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq(0)->andWhere('id')->in($idList)->fetchAll();
|
||||
foreach($repos as $i => $repo)
|
||||
{
|
||||
if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password);
|
||||
$repo->acl = json_decode($repo->acl);
|
||||
}
|
||||
|
||||
return $repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git branches.
|
||||
*
|
||||
@@ -296,6 +425,36 @@ class repoModel extends model
|
||||
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 git revisionName.
|
||||
*
|
||||
@@ -310,75 +469,6 @@ class repoModel extends model
|
||||
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();
|
||||
$this->dao->delete()->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save commit.
|
||||
*
|
||||
@@ -676,6 +766,7 @@ class repoModel extends model
|
||||
*/
|
||||
public function encodePath($path = '')
|
||||
{
|
||||
if(empty($path)) return $path;
|
||||
return helper::safe64Encode(urlencode($path));
|
||||
}
|
||||
|
||||
@@ -688,6 +779,7 @@ class repoModel extends model
|
||||
*/
|
||||
public function decodePath($path = '')
|
||||
{
|
||||
if(empty($path)) return $path;
|
||||
return trim(urldecode(helper::safe64Decode($path)), '/');
|
||||
}
|
||||
|
||||
@@ -801,7 +893,7 @@ class repoModel extends model
|
||||
$stories = array();
|
||||
$tasks = array();
|
||||
$bugs = array();
|
||||
$commonReg = "(?:\s){0,}((?:#|:|:){0,})([0-9, ]{1,})";
|
||||
$commonReg = "(?:\s){0,}((?:#|:|��){0,})([0-9, ]{1,})";
|
||||
$taskReg = '/task' . $commonReg . '/i';
|
||||
$storyReg = '/story' . $commonReg . '/i';
|
||||
$bugReg = '/bug' . $commonReg . '/i';
|
||||
@@ -848,4 +940,128 @@ class repoModel extends model
|
||||
}
|
||||
return $replaceLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the comment of git, extract object id list from it.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseComment($comment)
|
||||
{
|
||||
if(is_string($this->config->repo->matchComment)) $this->config->repo->matchComment = json_decode($this->config->repo->matchComment, true);
|
||||
$matchComment = $this->config->repo->matchComment;
|
||||
|
||||
$matches = array();
|
||||
$stories = array();
|
||||
$tasks = array();
|
||||
$bugs = array();
|
||||
$integrations = array();
|
||||
$actions = array();
|
||||
while(true)
|
||||
{
|
||||
$found = preg_match("/{$matchComment['id']['mark']}[0-9]+({$matchComment['id']['split']}[0-9]+)*/", $comment, $matches);
|
||||
if(empty($found)) break;
|
||||
if($found)
|
||||
{
|
||||
$position = strpos($comment, $matches[0]);
|
||||
$subComment = substr($comment, 0, $position + strlen($matches[0]));
|
||||
$comment = substr($comment, $position + strlen($matches[0]) + 1);
|
||||
|
||||
$idList = explode($matchComment['id']['mark'], str_replace($matchComment['id']['split'], '', $matches[0]));
|
||||
foreach($matchComment['module'] as $module => $moduleMatch)
|
||||
{
|
||||
if(stripos($subComment, $moduleMatch) !== false)
|
||||
{
|
||||
if($module == 'story')
|
||||
{
|
||||
foreach($idList as $id) $stories[$id] = $id;
|
||||
}
|
||||
elseif($module == 'task')
|
||||
{
|
||||
foreach($idList as $id) $tasks[$id] = $id;
|
||||
foreach($matchComment['task'] as $method => $match)
|
||||
{
|
||||
if(strpos($subComment, $match) !== false)
|
||||
{
|
||||
$consumed = 0;
|
||||
preg_match("/{$matchComment['task']['consumed']}{$matchComment['mark']['consumed']}([0-9]+)/", $comment, $costMatch);
|
||||
if($costMatch) $consumed = $costMatch[1];
|
||||
|
||||
$left = 0;
|
||||
preg_match("/{$matchComment['task']['left']}{$matchComment['mark']['left']}([0-9]+)/", $comment, $leftMatch);
|
||||
if($leftMatch) $left = $leftMatch[1];
|
||||
|
||||
foreach($idList as $id)
|
||||
{
|
||||
$actions['task'][$id]['action'] = $method;
|
||||
$actions['task'][$id]['consumed'] = $consumed;
|
||||
$actions['task'][$id]['left'] = $left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($module == 'bug')
|
||||
{
|
||||
foreach($idList as $id) $bugs[$id] = $id;
|
||||
foreach($matchComment['bug'] as $method => $match)
|
||||
{
|
||||
if(strpos($subComment, $match) !== false)
|
||||
{
|
||||
$buildID = 0;
|
||||
preg_match("/{$matchComment['bug']['resolvedBuild']}{$matchComment['mark']['resolvedBuild']}([0-9]+)/", $comment, $buildMatch);
|
||||
if($buildMatch) $buildID = $buildMatch[1];
|
||||
|
||||
foreach($idList as $id)
|
||||
{
|
||||
$actions['bug'][$id]['action'] = $method;
|
||||
$actions['bug'][$id]['resolvedBuild'] = $buildID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($module == 'integration')
|
||||
{
|
||||
foreach($idList as $id) $integrations[$id] = $id;
|
||||
foreach($matchComment['integration'] as $method => $match)
|
||||
{
|
||||
if(strpos($subComment, $match) !== false)
|
||||
{
|
||||
foreach($idList as $id) $actions['integration'][$id]['action'] = $method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs, 'integrations' => $integrations, 'actions' => $actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iconv Comment.
|
||||
*
|
||||
* @param string $comment
|
||||
* @param string $encodings
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function iconvComment($comment, $encodings)
|
||||
{
|
||||
/* Get encodings. */
|
||||
if($encodings == '') return $comment;
|
||||
$encodings = explode(',', $encodings);
|
||||
|
||||
/* Try convert. */
|
||||
foreach($encodings as $encoding)
|
||||
{
|
||||
if($encoding == 'utf-8') continue;
|
||||
$result = helper::convertEncoding($comment, $encoding);
|
||||
if($result) return $result;
|
||||
}
|
||||
|
||||
return $comment;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<?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: blame.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
include '../../common/view/header.html.php';
|
||||
js::import($jsRoot . 'misc/highlight/highlight.pack.js');
|
||||
css::import($jsRoot . 'misc/highlight/styles/github.css');
|
||||
?>
|
||||
<?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">
|
||||
<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 " <span class='label label-info'>" . $revisionName . '</span>';
|
||||
?>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<div class="code panel">
|
||||
<div class='panel-heading'>
|
||||
<div class='panel-title'><?php echo $entry;?></div>
|
||||
<?php $encodePath = $this->repo->encodePath($entry);?>
|
||||
<div class='panel-actions'>
|
||||
<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 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('blame', "repoID=$repoID&entry=&revision=$revision&encoding=$key", "entry=$encodePath"), $val)?></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<table class="blame table table-form table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class='w-70px'><?php echo $lang->repo->revision?></td>
|
||||
<?php if($repo->SCM == 'Git'):?>
|
||||
<td class='w-50px'><?php echo $lang->repo->commit?></td>
|
||||
<?php endif;?>
|
||||
<td class='w-100px'><?php echo $lang->repo->committer?></td>
|
||||
<td class="w-40px"><?php echo $lang->repo->line?></td>
|
||||
<td><?php echo $lang->repo->code?></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($blames as $blame):?>
|
||||
<tr<?php if(isset($blame['lines'])) echo " class='topLine'";?>>
|
||||
<?php
|
||||
if(isset($blame['lines']))
|
||||
{
|
||||
$rowspan = $blame['lines'];
|
||||
echo '<td rowspan="' . $rowspan . '" class="info" title="' . $blame['revision'] . '">';
|
||||
echo $repo->SCM == 'Git' ? substr($blame['revision'], 0, 10) : $blame['revision'];
|
||||
echo '</td>';
|
||||
if($repo->SCM == 'Git') echo '<td rowspan="' . $rowspan . '" class="info">' . zget($historys, $blame['revision'], '') . '</td>';
|
||||
echo '<td rowspan="' . $rowspan . '" class="info">' . $blame['committer'] . '</td>';
|
||||
}
|
||||
?>
|
||||
<td class="line"><?php echo $blame['line'];?></td>
|
||||
<td><pre><?php echo htmlspecialchars($blame['content']);?></pre></td>
|
||||
</tr>
|
||||
<?php endforeach?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -9,15 +9,88 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.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>
|
||||
<?php js::set('scm', 'Git')?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->repo->create; ?></h2>
|
||||
</div>
|
||||
<form id='repoForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='thWidth'><?php echo $lang->repo->type; ?></th>
|
||||
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, 'Git', "onchange='scmChanged(this.value)' class='form-control'"); ?></td>
|
||||
<td class="tips-git"><?php echo $lang->repo->synTips; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', '', "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->path; ?></th>
|
||||
<td class='required'><?php echo html::input('path', '', "class='form-control'"); ?></td>
|
||||
<td class='muted'>
|
||||
<span class="tips-git"><?php echo $lang->repo->example->path->git;?></span>
|
||||
<span class="tips-svn"><?php echo $lang->repo->example->path->svn;?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->encoding; ?></th>
|
||||
<td class='required'><?php echo html::input('encoding', 'utf-8', "class='form-control'"); ?></td>
|
||||
<td class='muted'><?php echo $lang->repo->encodingsTips; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->client;?></th>
|
||||
<td class='required'><?php echo html::input('client', '', "class='form-control'")?></td>
|
||||
<td class='muted'>
|
||||
<span class="tips-git"><?php echo $lang->repo->example->client->git;?></span>
|
||||
<span class="tips-svn"><?php echo $lang->repo->example->client->svn;?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="account-fields">
|
||||
<th><?php echo $lang->repo->account;?></th>
|
||||
<td><?php echo html::input('account', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr class="account-fields">
|
||||
<th><?php echo $lang->repo->password;?></th>
|
||||
<td>
|
||||
<?php echo html::password('password', '', "class='form-control'");?>
|
||||
</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>
|
||||
<th><?php echo $lang->repo->desc; ?></th>
|
||||
<td colspan='2'><?php echo html::textarea('desc', '', "rows='3' class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton(); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<form class='form-indicator main-form' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
@@ -80,4 +153,4 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* The edit view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package repo
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php if(common::checkNotCN()):?>
|
||||
<style>
|
||||
.user-addon{padding-right: 16px; padding-left: 16px;}
|
||||
</style>
|
||||
<?php endif;?>
|
||||
<?php js::set('scm', $repo->SCM)?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->repo->edit; ?></h2>
|
||||
</div>
|
||||
<form id='repoForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='thWidth'><?php echo $lang->repo->type; ?></th>
|
||||
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, $repo->SCM, "onchange='scmChanged(this.value)' class='form-control'"); ?></td>
|
||||
<td>
|
||||
<span class="tips-git"><?php echo $lang->repo->synTips; ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->name; ?></th>
|
||||
<td class='required'><?php echo html::input('name', $repo->name, "class='form-control'"); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->path; ?></th>
|
||||
<td class='required'><?php echo html::input('path', $repo->path, "class='form-control'"); ?></td>
|
||||
<td class='muted'>
|
||||
<span class="tips-git"><?php echo $lang->repo->example->path->git;?></span>
|
||||
<span class="tips-svn"><?php echo $lang->repo->example->path->svn;?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->encoding; ?></th>
|
||||
<td class='required'><?php echo html::input('encoding', $repo->encoding, "class='form-control'"); ?></td>
|
||||
<td class='muted'><?php echo $lang->repo->encodingsTips; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->client;?></th>
|
||||
<td class='required'><?php echo html::input('client', $repo->client, "class='form-control'")?></td>
|
||||
<td class='muted'>
|
||||
<span class="tips-git"><?php echo $lang->repo->example->client->git;?></span>
|
||||
<span class="tips-svn"><?php echo $lang->repo->example->client->svn;?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="account-fields">
|
||||
<th><?php echo $lang->repo->account;?></th>
|
||||
<td><?php echo html::input('account', $repo->account, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr class="account-fields">
|
||||
<th><?php echo $lang->repo->password;?></th>
|
||||
<td>
|
||||
<?php echo html::password('password', $repo->password, "class='form-control'");?>
|
||||
</td>
|
||||
<td></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>
|
||||
<th><?php echo $lang->repo->desc; ?></th>
|
||||
<td colspan='2'><?php echo html::textarea('desc', $repo->desc, "rows='3' class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php echo html::backButton() ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* The browse view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Gang Liu <liugang@cnezsoft.com>
|
||||
* @package repo
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id='mainContent'>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='repoList' class='table has-sort-head table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; ?>
|
||||
<th class='w-60px'><?php common::printOrderLink('id', $orderBy, $vars, $lang->repo->id); ?></th>
|
||||
<th class='w-120px'><?php common::printOrderLink('SCM', $orderBy, $vars, $lang->repo->type); ?></th>
|
||||
<th class='w-200px text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->repo->name); ?></th>
|
||||
<th class='text-left'><?php echo $lang->repo->path; ?></th>
|
||||
<th class='w-100px c-actions-4'><?php echo $lang->actions; ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($repoList as $id => $repo):?>
|
||||
<tr>
|
||||
<td class='text-center'><?php echo $id; ?></td>
|
||||
<td class='text'><?php echo zget($lang->repo->scmList, $repo->SCM); ?></td>
|
||||
<td class='text' title='<?php echo $repo->name; ?>'><?php echo $repo->name; ?></td>
|
||||
<td class='text' title='<?php echo $repo->path; ?>'><?php echo $repo->path; ?></td>
|
||||
<td class='text-left c-actions'>
|
||||
<?php
|
||||
common::printIcon('repo', 'edit', "repoID=$id", '', 'list', 'edit');
|
||||
if(common::hasPriv('repo', 'delete')) echo html::a($this->createLink('repo', 'delete', "repoID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->repo->delete}' class='btn'");
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($repoList):?>
|
||||
<div class='table-footer'><?php $pager->show('rignt', 'pagerjs');?></div>
|
||||
<?php endif;?>
|
||||
</form>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
/**
|
||||
* The setMatchComment view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.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="main-header">
|
||||
<h2><?php echo $lang->repo->setMatchComment;?></h2>
|
||||
</div>
|
||||
<form class='main-form form-ajax' method='post'>
|
||||
<table class='table table-form'>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class='w-100px'><?php echo $lang->repo->selectModule;?></th>
|
||||
<td class='w-200px'>
|
||||
<?php
|
||||
foreach($config->repo->matchComment['module'] as $module => $match) $modules[$module] = $lang->{$module}->common;
|
||||
echo html::select('selectModule', $modules, $selectModule, "class='form-control chosen'");
|
||||
?>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class='w-100px'><?php echo $lang->repo->module;?></th>
|
||||
<td>
|
||||
<?php foreach($config->repo->matchComment['module'] as $module => $match):?>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon hidden <?php echo $module . 'Item';?>'><?php echo $lang->{$module}->common;?></span>
|
||||
<?php echo html::input("matchComment[module][{$module}]", $match, "class='form-control hidden {$module}Item'");?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='taskItem hidden'>
|
||||
<th><?php echo $lang->task->common;?></th>
|
||||
<td colspan='2'>
|
||||
<div class='input-group'>
|
||||
<?php foreach($config->repo->matchComment['task'] as $method => $match):?>
|
||||
<span class='input-group-addon'><?php echo $lang->task->$method;?></span>
|
||||
<?php echo html::input("matchComment[task][{$method}]", $match, "class='form-control'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='bugItem hidden'>
|
||||
<th><?php echo $lang->bug->common;?></th>
|
||||
<td colspan='2'>
|
||||
<div class='input-group'>
|
||||
<?php foreach($config->repo->matchComment['bug'] as $method => $match):?>
|
||||
<span class='input-group-addon'><?php echo $lang->bug->$method;?></span>
|
||||
<?php echo html::input("matchComment[bug][{$method}]", $match, "class='form-control'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='integrationItem hidden'>
|
||||
<th><?php echo $lang->integration->common;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php foreach($config->repo->matchComment['integration'] as $method => $match):?>
|
||||
<span class='input-group-addon'><?php echo $lang->integration->$method;?></span>
|
||||
<?php echo html::input("matchComment[integration][{$method}]", $match, "class='form-control'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->idAB;?></th>
|
||||
<td colspan='2'>
|
||||
<div class='input-group'>
|
||||
<?php foreach($config->repo->matchComment['id'] as $method => $match):?>
|
||||
<span class='input-group-addon'><?php echo $lang->repo->$method;?></span>
|
||||
<?php echo html::input("matchComment[id][{$method}]", $match, "class='form-control'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='taskItem bugItem hidden'>
|
||||
<th><?php echo $lang->repo->mark;?></th>
|
||||
<td colspan='2'>
|
||||
<div class='input-group'>
|
||||
<?php foreach($config->repo->matchComment['mark'] as $method => $match):?>
|
||||
<?php $module = isset($lang->task->$method) ? 'task' : 'bug';?>
|
||||
<span class='input-group-addon hidden <?php echo $module . 'Item';?>'><?php echo $lang->{$module}->$method?></span>
|
||||
<?php echo html::input("matchComment[mark][{$method}]", $match, "class='form-control hidden {$module}Item'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->matchComment->exampleLabel;?></th>
|
||||
<td colspan='2' id='example'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' class='text-center'>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<?php js::set('matchCommentExample', $lang->repo->matchComment->example);?>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$('#selectModule').change()
|
||||
$('input').keyup(function(){replaceExample()});
|
||||
})
|
||||
|
||||
$('#selectModule').change(function()
|
||||
{
|
||||
var module = $(this).val();
|
||||
$('[class*=Item]').addClass('hidden');
|
||||
$('.' + module + 'Item').removeClass('hidden');
|
||||
replaceExample();
|
||||
})
|
||||
|
||||
function replaceExample()
|
||||
{
|
||||
var module = $('#selectModule').val();
|
||||
var html = '';
|
||||
if(module == 'story')
|
||||
{
|
||||
html = matchCommentExample['story']['common'].replace('%story%', $('[id*=module][id*=story]').val())
|
||||
.replace('%id%', $('[id*=id][id*=mark]').val())
|
||||
.replace('%split%', $('[id*=id][id*=split]').val());
|
||||
}
|
||||
else if(module == 'task')
|
||||
{
|
||||
html = matchCommentExample['task']['start'].replace('%start%', $('[id*=start').val())
|
||||
.replace('%task%', $('[id*=module][id*=task]').val())
|
||||
.replace('%id%', $('[id*=id][id*=mark]').val())
|
||||
.replace('%split%', $('[id*=id][id*=split]').val())
|
||||
.replace('%cost%', $('[id*=task][id*=consumed]').val())
|
||||
.replace('%consumedmark%', $('[id*=mark][id*=consumed]').val())
|
||||
.replace('%left%', $('[id*=task][id*=left]').val())
|
||||
.replace('%leftmark%', $('[id*=mark][id*=left]').val());
|
||||
html += '<br />' + matchCommentExample['task']['finish'].replace('%finish%', $('[id*=finish]').val())
|
||||
.replace('%task%', $('[id*=module][id*=task]').val())
|
||||
.replace('%id%', $('[id*=id][id*=mark]').val())
|
||||
.replace('%split%', $('[id*=id][id*=split]').val())
|
||||
.replace('%cost%', $('[id*=task][id*=consumed]').val())
|
||||
.replace('%consumedmark%', $('[id*=mark][id*=consumed]').val());
|
||||
}
|
||||
else if(module == 'bug')
|
||||
{
|
||||
html = matchCommentExample['bug']['resolve'].replace('%resolve%', $('[id*=bug][id*="resolve\]"]').val())
|
||||
.replace('%bug%', $('[id*=module][id*=bug]').val())
|
||||
.replace('%id%', $('[id*=id][id*=mark]').val())
|
||||
.replace('%split%', $('[id*=id][id*=split]').val())
|
||||
.replace('%resolvedBuild%', $('[id*=bug][id*=resolvedBuild]').val())
|
||||
.replace('%buildmark%', $('[id*=mark][id*=resolvedBuild]').val());
|
||||
}
|
||||
else if(module == 'integration')
|
||||
{
|
||||
html = matchCommentExample['integration']['start'].replace('%build%', $('[id*=integration][id*=start]').val())
|
||||
.replace('%integration%', $('[id*=module][id*=integration]').val())
|
||||
.replace('%id%', $('[id*=id][id*=mark]').val())
|
||||
.replace('%split%', $('[id*=id][id*=split]').val())
|
||||
}
|
||||
|
||||
$('#example').html(html);
|
||||
}
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -1,87 +0,0 @@
|
||||
<?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 class='required'><?php echo html::input('name', $repo->name, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->path;?></th>
|
||||
<td class='required'><?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 class='required'><?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 class='required'><?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';?>
|
||||
@@ -33,7 +33,7 @@ $(function(){
|
||||
if(data == 'finish')
|
||||
{
|
||||
$('#caption').text('<?php echo $lang->repo->notice->syncComplete?>');
|
||||
return self.location = createLink('repo', 'browse', "repoID=<?php echo $repoID?>");
|
||||
return self.location = createLink('repo', 'maintain');
|
||||
}
|
||||
$('#commits').html(parseInt($('#commits').html()) + parseInt(data));
|
||||
setTimeout(syncComments, 10);
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
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');
|
||||
js::import($jsRoot . 'misc/highlight/highlight.pack.js');
|
||||
$encodePath = $this->repo->encodePath($entry);
|
||||
$version = " <span class=\"label label-info\">$revisionName</span>";
|
||||
?>
|
||||
@@ -56,6 +56,7 @@ $version = " <span class=\"label label-info\">$revisionName</span>";
|
||||
<div class='panel-actions'>
|
||||
<?php if($suffix != 'binary' and strpos($config->repo->images, "|$suffix|") === false):?>
|
||||
<?php
|
||||
if(common::hasPriv('repo', 'blame')) echo html::a($this->repo->createLink('blame', "repoID=$repoID&entry=&revision=$revision&encoding=$encoding", "entry=$encodePath"), html::icon('random') . $lang->repo->blame, '', "class='btn btn-sm btn-primary'");
|
||||
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;?>
|
||||
|
||||
@@ -266,10 +266,11 @@ class storyModel extends model
|
||||
public function batchCreate($productID = 0, $branch = 0, $type = 'story')
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$branch = (int)$branch;
|
||||
$now = helper::now();
|
||||
$mails = array();
|
||||
$stories = fixer::input('post')->get();
|
||||
$branch = (int)$branch;
|
||||
$productID = (int)$productID;
|
||||
$now = helper::now();
|
||||
$mails = array();
|
||||
$stories = fixer::input('post')->get();
|
||||
|
||||
$result = $this->loadModel('common')->removeDuplicate('story', $stories, "product={$productID}");
|
||||
$stories = $result['data'];
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
* $config->svn->repos['pms']['password'] = 'pass';
|
||||
*
|
||||
*/
|
||||
|
||||
$config->svn->tagRequiredFields = 'name,repo';
|
||||
|
||||
/* will use the config of repo records in db
|
||||
$config->svn = new stdClass();
|
||||
$config->svn->encodings = 'utf-8';
|
||||
$config->svn->client = '';
|
||||
@@ -25,7 +29,6 @@ $config->svn->repos[$i]['encoding'] = 'utf-8';
|
||||
$config->svn->repos[$i]['username'] = '';
|
||||
$config->svn->repos[$i]['password'] = '';
|
||||
|
||||
/*
|
||||
$i ++;
|
||||
$config->svn->repos[$i]['path'] = '';
|
||||
$config->svn->repos[$i]['username'] = '';
|
||||
|
||||
@@ -37,10 +37,9 @@ class svn extends control
|
||||
$url = helper::safe64Decode($url);
|
||||
if(common::hasPriv('repo', 'diff'))
|
||||
{
|
||||
$repos = $this->loadModel('repo')->getAllRepos();
|
||||
foreach($repos as $repo)
|
||||
$svnRepos = $this->loadModel('repo')->getListBySCM('Subversion', 'haspriv');
|
||||
foreach($svnRepos as $repo)
|
||||
{
|
||||
if($repo->SCM != 'Subversion') continue;
|
||||
if(strpos(strtolower($url), strtolower($repo->path)) === 0)
|
||||
{
|
||||
$entry = $this->repo->encodePath(str_ireplace($repo->path, '', $url));
|
||||
@@ -72,10 +71,9 @@ class svn extends control
|
||||
$url = helper::safe64Decode($url);
|
||||
if(common::hasPriv('repo', 'view'))
|
||||
{
|
||||
$repos = $this->loadModel('repo')->getAllRepos();
|
||||
$repos = $this->loadModel('repo')->getListBySCM('Subversion', 'haspriv');
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
if($repo->SCM != 'Subversion') continue;
|
||||
if(strpos(strtolower($url), strtolower($repo->path)) === 0)
|
||||
{
|
||||
$entry = $this->repo->encodePath(str_ireplace(strtolower($repo->path), '', $url));
|
||||
@@ -109,9 +107,11 @@ class svn extends control
|
||||
$parsedLogs[] = $this->svn->convertLog($entry);
|
||||
}
|
||||
$parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array());
|
||||
$this->loadModel('repo');
|
||||
foreach($parsedLogs as $log)
|
||||
{
|
||||
$objects = $this->svn->parseComment($log->msg);
|
||||
$objects = $this->repo->parseComment($log->msg);
|
||||
|
||||
if($objects)
|
||||
{
|
||||
$this->svn->saveAction2PMS($objects, $log, $repoRoot);
|
||||
@@ -170,7 +170,8 @@ class svn extends control
|
||||
$parsedFiles[$action][] = $path;
|
||||
}
|
||||
|
||||
$objects = $this->svn->parseComment($message);
|
||||
$objects = $this->loadModel('repo')->parseComment($message);
|
||||
|
||||
if($objects)
|
||||
{
|
||||
$log = new stdclass();
|
||||
|
||||
+164
-153
@@ -71,6 +71,7 @@ class svnModel extends model
|
||||
{
|
||||
parent::__construct();
|
||||
$this->loadModel('action');
|
||||
$this->loadModel('repo');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,47 +91,57 @@ class svnModel extends model
|
||||
foreach($this->repos as $name => $repo)
|
||||
{
|
||||
$this->printLog("begin repo $name");
|
||||
$repo = (object)$repo;
|
||||
$repo->name = $name;
|
||||
if(!$this->setRepo($repo)) return false;
|
||||
|
||||
$savedRevision = $this->getSavedRevision();
|
||||
$this->printLog("start from revision $savedRevision");
|
||||
$logs = $this->getRepoLogs($repo, $savedRevision);
|
||||
if(empty($logs)) continue;
|
||||
|
||||
$this->printLog("get " . count($logs) . " logs");
|
||||
$this->printLog('begin parsing logs');
|
||||
foreach($logs as $log)
|
||||
$logs = $this->getRepoLogs($repo, $savedRevision);
|
||||
$objects = array();
|
||||
if(!empty($logs))
|
||||
{
|
||||
$this->printLog("parsing log {$log->revision}");
|
||||
if($log->revision == $savedRevision)
|
||||
$this->printLog("get " . count($logs) . " logs");
|
||||
$this->printLog('begin parsing logs');
|
||||
|
||||
foreach($logs as $log)
|
||||
{
|
||||
$this->printLog("{$log->revision} alread parsed, ommit it");
|
||||
continue;
|
||||
$this->printLog("parsing log {$log->revision}");
|
||||
if($log->revision == $savedRevision)
|
||||
{
|
||||
$this->printLog("{$log->revision} alread parsed, commit it");
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------");
|
||||
|
||||
$objects = $this->repo->parseComment($log->msg);
|
||||
if($objects)
|
||||
{
|
||||
$this->printLog('extract' .
|
||||
'story:' . join(' ', $objects['stories']) .
|
||||
' task:' . join(' ', $objects['tasks']) .
|
||||
' bug:' . join(',', $objects['bugs']));
|
||||
|
||||
$this->saveAction2PMS($objects, $log, $repo->encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->printLog('no objects found' . "\n");
|
||||
}
|
||||
|
||||
if($log->revision > $savedRevision) $savedRevision = $log->revision;
|
||||
}
|
||||
|
||||
$this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------");
|
||||
$objects = $this->parseComment($log->msg);
|
||||
if($objects)
|
||||
{
|
||||
$this->printLog('extract' .
|
||||
'story:' . join(' ', $objects['stories']) .
|
||||
' task:' . join(' ', $objects['tasks']) .
|
||||
' bug:' . join(',', $objects['bugs']));
|
||||
|
||||
$this->saveAction2PMS($objects, $log);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->printLog('no objects found' . "\n");
|
||||
}
|
||||
if($log->revision > $savedRevision) $savedRevision = $log->revision;
|
||||
$this->saveLastRevision($savedRevision);
|
||||
$this->printLog("save revision $savedRevision");
|
||||
$this->deleteRestartFile();
|
||||
$this->printLog("\n\nrepo #" . $repo->id . ': ' . $repo->path . " finished");
|
||||
}
|
||||
$this->saveLastRevision($savedRevision);
|
||||
$this->printLog("save revision $savedRevision");
|
||||
$this->deleteRestartFile();
|
||||
$this->printLog("\n\nrepo $name finished");
|
||||
|
||||
// exe ci jobs in log
|
||||
$cijobIdList = zget($objects, 'integrations', array());
|
||||
$this->loadModel('compile');
|
||||
foreach($cijobIdList as $id) $this->compile->execByCompile($id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +157,19 @@ class svnModel extends model
|
||||
if(!is_dir($this->logRoot)) mkdir($this->logRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tag file of a repo.
|
||||
*
|
||||
* @param string $repoId
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setTagFile($repoId)
|
||||
{
|
||||
$this->setLogRoot();
|
||||
$this->tagFile = $this->logRoot . $repoId . '.tag';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the restart file.
|
||||
*
|
||||
@@ -176,13 +200,46 @@ class svnModel extends model
|
||||
*/
|
||||
public function setRepos()
|
||||
{
|
||||
if(!$this->config->svn->repos)
|
||||
$repos = $this->loadModel('repo')->getListBySCM('Subversion');
|
||||
|
||||
$svnRepos = array();
|
||||
$paths = array();
|
||||
|
||||
foreach($repos as $repo)
|
||||
{
|
||||
echo "You must set one svn repo.\n";
|
||||
return false;
|
||||
if(isset($paths[$repo->path])) continue;
|
||||
|
||||
unset($repo->acl);
|
||||
unset($repo->desc);
|
||||
$svnRepos[] = $repo;
|
||||
$paths[$repo->path] = $repo->path;
|
||||
}
|
||||
|
||||
$this->repos = $this->config->svn->repos;
|
||||
if(isset($this->config->svn->repos))
|
||||
{
|
||||
foreach($this->config->svn->repos as $i => $repo)
|
||||
{
|
||||
$repoPath = $repo['path'];
|
||||
if(empty($repoPath)) continue;
|
||||
if(isset($paths[$repoPath])) continue;
|
||||
|
||||
$svnRepo = new stdclass();
|
||||
$svnRepo->id = "c{$i}";
|
||||
$svnRepo->client = $this->config->svn->client;
|
||||
$svnRepo->path = $repoPath;
|
||||
$svnRepo->prefix = '';
|
||||
$svnRepo->SCM = 'Subversion';
|
||||
$svnRepo->account = $repo['username'];
|
||||
$svnRepo->password = $repo['password'];
|
||||
$svnRepo->encoding = zget($repo, 'encoding', $this->config->svn->client);
|
||||
|
||||
$svnRepos[] = $svnRepo;
|
||||
$paths[$repoPath] = $repoPath;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($svnRepos)) echo "You must set one svn repo.\n";
|
||||
$this->repos = $svnRepos;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,7 +274,8 @@ class svnModel extends model
|
||||
$this->setClient($repo);
|
||||
if(empty($this->client)) return false;
|
||||
|
||||
$this->setLogFile($repo->name);
|
||||
$this->setLogFile($repo->id);
|
||||
$this->setTagFile($repo->id);
|
||||
$this->setRepoRoot($repo);
|
||||
return true;
|
||||
}
|
||||
@@ -231,23 +289,17 @@ class svnModel extends model
|
||||
*/
|
||||
public function setClient($repo)
|
||||
{
|
||||
if($this->config->svn->client == '')
|
||||
{
|
||||
echo "You must set the svn client file.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->client = $this->config->svn->client . " --non-interactive";
|
||||
$this->client = $repo->client . " --non-interactive";
|
||||
if(stripos($repo->path, 'https') === 0 or stripos($repo->path, 'svn') === 0)
|
||||
{
|
||||
$cmd = $this->config->svn->client . ' --version --quiet';
|
||||
$cmd = $repo->client . ' --version --quiet';
|
||||
$version = `$cmd`;
|
||||
if(version_compare($version, '1.6.0', '>'))
|
||||
{
|
||||
$this->client .= ' --trust-server-cert';
|
||||
}
|
||||
}
|
||||
if(isset($repo->username)) $this->client .= " --username $repo->username --password $repo->password --no-auth-cache";
|
||||
if(isset($repo->account)) $this->client .= " --username $repo->account --password $repo->password --no-auth-cache";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -258,9 +310,9 @@ class svnModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setLogFile($repoName)
|
||||
public function setLogFile($repoId)
|
||||
{
|
||||
$this->logFile = $this->logRoot . $repoName;
|
||||
$this->logFile = $this->logRoot . $repoId . '.log';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,11 +324,24 @@ class svnModel extends model
|
||||
*/
|
||||
public function setRepoRoot($repo)
|
||||
{
|
||||
$cmd = $this->client . " info --xml $repo->path";
|
||||
$info = `$cmd`;
|
||||
$info = simplexml_load_string($info);
|
||||
$repoRoot = $info->entry->repository->root;
|
||||
$this->repoRoot = $repoRoot;
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
$info = $scm->info('');
|
||||
$this->repoRoot = $info->root;
|
||||
}
|
||||
|
||||
/**
|
||||
* get tags histories for repo.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getRepoTags($repo, $path)
|
||||
{
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
return $scm->tags($path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,110 +354,24 @@ class svnModel extends model
|
||||
*/
|
||||
public function getRepoLogs($repo, $fromRevision)
|
||||
{
|
||||
$parsedLogs = array();
|
||||
|
||||
/* The svn log command. */
|
||||
$cmd = $this->client . " log -r $fromRevision:HEAD -v --xml $repo->path";
|
||||
$rawLogs = `$cmd`;
|
||||
$logs = @simplexml_load_string($rawLogs); // Convert it to object.
|
||||
if(!$logs)
|
||||
{
|
||||
echo "Some error occers: \nThe command is $cmd\n the svn logs is $rawLogs\n";
|
||||
return false;
|
||||
}
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
$logs = $scm->log('', $fromRevision);
|
||||
if(empty($logs)) return false;
|
||||
|
||||
/* Process logs. */
|
||||
foreach($logs->logentry as $entry) $parsedLogs[] = $this->convertLog($entry);
|
||||
return $parsedLogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert log from xml format to object.
|
||||
*
|
||||
* @param object $log
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function convertLog($log)
|
||||
{
|
||||
/* Get author, revision, msg, date attributes. */
|
||||
$parsedLog = new stdClass();
|
||||
$parsedLog->author = (string)$log->author;
|
||||
$parsedLog->revision = (int)$log['revision'];
|
||||
$parsedLog->msg = trim((string)$log->msg);
|
||||
$parsedLog->date = date('Y-m-d H:i:s', strtotime($log->date));
|
||||
|
||||
/* Process files. */
|
||||
$parsedLog->files = array();
|
||||
foreach ($log->paths as $key => $paths)
|
||||
foreach($logs as $log)
|
||||
{
|
||||
$parsedFiles = array();
|
||||
foreach($paths as $path)
|
||||
{
|
||||
$action = (string)$path['action'];
|
||||
$parsedFiles[$action][] = (string)$path;
|
||||
}
|
||||
$log->author = $log->committer;
|
||||
$log->msg = $log->comment;
|
||||
$log->date = $log->time;
|
||||
|
||||
/* Process files. */
|
||||
$log->files = array();
|
||||
foreach($log->change as $file => $info) $log->files[$info['action']][] = $file;
|
||||
}
|
||||
$parsedLog->files = $parsedFiles;
|
||||
|
||||
return $parsedLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the comment of svn, extract object id list from it.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function parseComment($comment)
|
||||
{
|
||||
$stories = array();
|
||||
$tasks = array();
|
||||
$bugs = array();
|
||||
|
||||
// bug|story|task(case insensitive) + some space + #|:|:(Chinese) + id lists(maybe join with space or ,)
|
||||
// $comment = "bug # 1,2,3,4 Bug:1 2 3 4 5 story:9999,1234566 story:456,1234566";
|
||||
$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)) $stories = join(' ', $result[1]);
|
||||
if(preg_match_all($taskReg, $comment, $result)) $tasks = join(' ', $result[1]);
|
||||
if(preg_match_all($bugReg, $comment, $result)) $bugs = join(' ', $result[1]);
|
||||
|
||||
if($stories) $stories = array_unique(explode(' ', str_replace(',', ' ', $stories)));
|
||||
if($tasks) $tasks = array_unique(explode(' ', str_replace(',', ' ', $tasks)));
|
||||
if($bugs) $bugs = array_unique(explode(' ', str_replace(',', ' ', $bugs)));
|
||||
|
||||
if(!$stories and !$tasks and !$bugs) return array();
|
||||
return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the comment to uft-8.
|
||||
*
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function iconvComment($comment)
|
||||
{
|
||||
/* Get encodings. */
|
||||
$encodings = str_replace(' ', '', isset($this->config->svn->encodings) ? $this->config->svn->encodings : '');
|
||||
if($encodings == '') return $comment;
|
||||
$encodings = explode(',', $encodings);
|
||||
|
||||
/* Try convert. */
|
||||
foreach($encodings as $encoding)
|
||||
{
|
||||
if($encoding == 'utf-8') continue;
|
||||
$result = helper::convertEncoding($comment, $encoding);
|
||||
if($result) return $result;
|
||||
}
|
||||
|
||||
return $comment;
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -482,13 +461,14 @@ class svnModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveAction2PMS($objects, $log, $repoRoot = '')
|
||||
public function saveAction2PMS($objects, $log, $repoRoot = '', $encodings = 'utf-8')
|
||||
{
|
||||
$action = new stdclass();
|
||||
$action->actor = $log->author;
|
||||
$action->action = 'svncommited';
|
||||
$action->date = $log->date;
|
||||
$action->comment = htmlspecialchars($this->iconvComment($log->msg));
|
||||
|
||||
$action->comment = htmlspecialchars($this->repo->iconvComment($log->msg, $encodings));
|
||||
$action->extra = $log->revision;
|
||||
|
||||
$changes = $this->createActionChanges($log, $repoRoot);
|
||||
@@ -732,4 +712,35 @@ class svnModel extends model
|
||||
|
||||
return $buildedURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the saved tag.
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getSavedTag($repoID = 0)
|
||||
{
|
||||
if($repoID) $this->setTagFile($repoID);
|
||||
if(!file_exists($this->tagFile)) return array();
|
||||
if(file_exists($this->restartFile)) return array();
|
||||
|
||||
$tags = array();
|
||||
foreach(json_decode(file_get_contents($this->tagFile)) as $tag) $tags[$tag] = $tag;
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the last revision.
|
||||
*
|
||||
* @param int $tag
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveLastTag($tag, $repoId = 0)
|
||||
{
|
||||
if($repoId) $this->setTagFile($repoId);
|
||||
if(is_array($tag)) $tag = json_encode($tag);
|
||||
file_put_contents($this->tagFile, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,12 @@ class taskModel extends model
|
||||
dao::$errors[] = $this->lang->task->error->recordMinus;
|
||||
return false;
|
||||
}
|
||||
$projectID = (int)$projectID;
|
||||
$taskIdList = array();
|
||||
$taskFiles = array();
|
||||
$this->loadModel('file');
|
||||
$task = fixer::input('post')
|
||||
->setDefault('project', (int)$projectID)
|
||||
->setDefault('project', $projectID)
|
||||
->setDefault('estimate,left,story', 0)
|
||||
->setDefault('status', 'wait')
|
||||
->setIF($this->post->estimate != false, 'left', $this->post->estimate)
|
||||
@@ -65,7 +66,7 @@ class taskModel extends model
|
||||
/* Check duplicate task. */
|
||||
if($task->type != 'affair')
|
||||
{
|
||||
$result = $this->loadModel('common')->removeDuplicate('task', $task, "project=$projectID and story=" . (int)$task->story);
|
||||
$result = $this->loadModel('common')->removeDuplicate('task', $task, "project={$projectID} and story=" . (int)$task->story);
|
||||
if($result['stop'])
|
||||
{
|
||||
$taskIdList[$assignedTo] = array('status' => 'exists', 'id' => $result['duplicate']);
|
||||
|
||||
@@ -242,6 +242,7 @@ class testcaseModel extends model
|
||||
function batchCreate($productID, $branch, $storyID)
|
||||
{
|
||||
$branch = (int)$branch;
|
||||
$productID = (int)$productID;
|
||||
$now = helper::now();
|
||||
$cases = fixer::input('post')->get();
|
||||
|
||||
|
||||
@@ -42,9 +42,11 @@ Copyright (c) Vladimir Gubarkov <xonixx@gmail.com>
|
||||
}
|
||||
|
||||
function copyToBuffer(textToCopy) {
|
||||
if (window.clipboardData) { // IE
|
||||
if (window.clipboardData)
|
||||
{ // IE
|
||||
window.clipboardData.setData("Text", textToCopy);
|
||||
} else if (window.netscape) { // FF
|
||||
} 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);
|
||||
|
||||
+3
-3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user