diff --git a/lib/scm/gitlab.class.php b/lib/scm/gitlab.class.php
index 200bf61b15..799b674608 100644
--- a/lib/scm/gitlab.class.php
+++ b/lib/scm/gitlab.class.php
@@ -549,10 +549,11 @@ class gitlab
* @param string $version
* @param int $count
* @param string $branch
+ * @param bool $getFile
* @access public
* @return array
*/
- public function getCommits($version = '', $count = 0, $branch = '')
+ public function getCommits($version = '', $count = 0, $branch = '', $getFile = false)
{
if(!scm::checkRevision($version)) return array();
$api = "commits";
@@ -620,7 +621,7 @@ class gitlab
$log->time = date('Y-m-d H:i:s', strtotime($commit->created_at));
$commits[$commit->id] = $log;
- $files[$commit->id] = $this->getFilesByCommit($log->revision);
+ if($getFile) $files[$commit->id] = $this->getFilesByCommit($log->revision);
}
return array('commits' => $commits, 'files' => $files);
@@ -653,10 +654,12 @@ class gitlab
* @param string $fromRevision
* @param string $toRevision
* @param int $perPage
+ * @param int $page
+ * @param bool $getUrl
* @access public
* @return array
*/
- public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0)
+ public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0, $page = 1, $getUrl = false)
{
$path = ltrim($path, DIRECTORY_SEPARATOR);
$api = "commits";
@@ -683,6 +686,18 @@ class gitlab
if($until) $param->until = $until;
if($perPage) $param->per_page = $perPage;
+ if($page) $param->page = $page;
+
+ if($getUrl)
+ {
+ $params = (array) $param;
+ $params['private_token'] = $this->token;
+ $params['per_page'] = isset($params['per_page']) ? $params['per_page'] : 100;
+
+ $api = ltrim($api, '/');
+ $api = $this->root . $api . '?' . http_build_query($params);
+ return $api;
+ }
return $this->fetch($api, $param);
}
@@ -736,10 +751,11 @@ class gitlab
*
* @param string $path
* @param bool $recursive
+ * @param bool $loop
* @access public
* @return mixed
*/
- public function tree($path, $recursive = 1)
+ public function tree($path, $recursive = 1, $loop = false)
{
$api = "tree";
@@ -747,17 +763,20 @@ class gitlab
$params['path'] = ltrim($path, '/');
$params['ref'] = $this->branch;
$params['recursive'] = (int) $recursive;
- return $this->fetch($api, $params);
+ return $this->fetch($api, $params, $loop, $loop ? true : false);
}
/**
* Fetch data from gitlab api.
*
* @param string $api
+ * @param array $params
+ * @param bool $needToLoop
+ * @param bool $multi
* @access public
* @return mixed
*/
- public function fetch($api, $params = array(), $needToLoop = false)
+ public function fetch($api, $params = array(), $needToLoop = false, $multi = false)
{
$params = (array) $params;
$params['private_token'] = $this->token;
@@ -768,19 +787,49 @@ class gitlab
if($needToLoop)
{
$allResults = array();
- for($page = 1; true; $page++)
+ if($multi)
{
- $results = json_decode(commonModel::http($api . "&page={$page}"));
- if(!is_array($results)) break;
- if(!empty($results)) $allResults = array_merge($allResults, $results);
- if(count($results) < 100) break;
+ $results = commonModel::httpWithHeader($api . "&page=1");
+ if(empty($results['header']['X-Total-Pages'])) return array();
+
+ $totalPages = $results['header']['X-Total-Pages'];
+ if($totalPages == 1)
+ {
+ $allResults = json_decode($results['body']);
+ }
+ else
+ {
+ $requests = array();
+ for($page = 1; $page <= $totalPages; $page++)
+ {
+ $requests[$page]['url'] = $api . "&page={$page}";
+ }
+
+ $results = requests::request_multiple($requests, array('timeout' => 60));
+ foreach($results as $result)
+ {
+ if(empty($result->body)) continue;
+ $data = json_decode($result->body);
+ $allResults = array_merge($allResults, $data);
+ }
+ }
+ }
+ else
+ {
+ for($page = 1; true; $page++)
+ {
+ $results = json_decode(commonModel::http($api . "&page={$page}", null, array(), array(), 'data', 'POST', 30, true, false));
+ if(!is_array($results)) break;
+ if(!empty($results)) $allResults = array_merge($allResults, $results);
+ if(count($results) < 100) break;
+ }
}
return $allResults;
}
else
{
- list($response, $httpCode) = commonModel::http($api, null, array(), array(), 'data', 'Post', 30, true);
+ list($response, $httpCode) = commonModel::http($api, null, array(), array(), 'data', 'POST', 30, true, false);
if(!empty(commonModel::$requestErrors))
{
commonModel::$requestErrors = array();
@@ -828,12 +877,15 @@ class gitlab
$parsedLog->time = date('Y-m-d H:i:s', strtotime($commit->committed_date));
$parsedLog->comment = $commit->message;
$parsedLog->change = array();
- foreach($commit->diffs as $diff)
+ if(!empty($commit->diffs))
{
- $parsedLog->change[$diff->path] = array();
- $parsedLog->change[$diff->path]['action'] = $diff->action;
- $parsedLog->change[$diff->path]['kind'] = $diff->type;
- $parsedLog->change[$diff->path]['oldPath'] = $diff->oldPath;
+ foreach($commit->diffs as $diff)
+ {
+ $parsedLog->change[$diff->path] = array();
+ $parsedLog->change[$diff->path]['action'] = $diff->action;
+ $parsedLog->change[$diff->path]['kind'] = $diff->type;
+ $parsedLog->change[$diff->path]['oldPath'] = $diff->oldPath;
+ }
}
$parsedLogs[] = $parsedLog;
}
diff --git a/module/common/model.php b/module/common/model.php
index 3bf311ce61..f895006831 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -3181,18 +3181,21 @@ EOD;
curl_close($curl);
- $logFile = $app->getLogRoot() . 'saas.'. date('Ymd') . '.log.php';
- if(!file_exists($logFile)) file_put_contents($logFile, '');
-
- $fh = @fopen($logFile, 'a');
- if($fh)
+ if($app->config->debug)
{
- fwrite($fh, date('Ymd H:i:s') . ": " . $app->getURI() . "\n");
- fwrite($fh, "url: " . $url . "\n");
- if(!empty($data)) fwrite($fh, "data: " . print_r($data, true) . "\n");
- fwrite($fh, "results:" . print_r($response, true) . "\n");
- if(!empty($errors)) fwrite($fh, "errors: " . $errors . "\n");
- fclose($fh);
+ $logFile = $app->getLogRoot() . 'saas.'. date('Ymd') . '.log.php';
+ if(!file_exists($logFile)) file_put_contents($logFile, '');
+
+ $fh = @fopen($logFile, 'a');
+ if($fh)
+ {
+ fwrite($fh, date('Ymd H:i:s') . ": " . $app->getURI() . "\n");
+ fwrite($fh, "url: " . $url . "\n");
+ if(!empty($data)) fwrite($fh, "data: " . print_r($data, true) . "\n");
+ fwrite($fh, "results:" . print_r($response, true) . "\n");
+ if(!empty($errors)) fwrite($fh, "errors: " . $errors . "\n");
+ fclose($fh);
+ }
}
if($errors) commonModel::$requestErrors[] = $errors;
@@ -3211,11 +3214,12 @@ EOD;
* @param string $method POST|PATCH|PUT
* @param int $timeout
* @param bool $httpCode
+ * @param bool $log
* @static
* @access public
* @return string
*/
- public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false)
+ public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = true)
{
global $lang, $app;
if(!extension_loaded('curl'))
@@ -3265,18 +3269,21 @@ EOD;
if($httpCode) $httpCode = curl_getinfo($curl,CURLINFO_HTTP_CODE);
curl_close($curl);
- $logFile = $app->getLogRoot() . 'saas.'. date('Ymd') . '.log.php';
- if(!file_exists($logFile)) file_put_contents($logFile, '');
-
- $fh = @fopen($logFile, 'a');
- if($fh)
+ if($log or $app->config->debug)
{
- fwrite($fh, date('Ymd H:i:s') . ": " . $app->getURI() . "\n");
- fwrite($fh, "url: " . $url . "\n");
- if(!empty($data)) fwrite($fh, "data: " . print_r($data, true) . "\n");
- fwrite($fh, "results:" . print_r($response, true) . "\n");
- if(!empty($errors)) fwrite($fh, "errors: " . $errors . "\n");
- fclose($fh);
+ $logFile = $app->getLogRoot() . 'saas.'. date('Ymd') . '.log.php';
+ if(!file_exists($logFile)) file_put_contents($logFile, '');
+
+ $fh = @fopen($logFile, 'a');
+ if($fh)
+ {
+ fwrite($fh, date('Ymd H:i:s') . ": " . $app->getURI() . "\n");
+ fwrite($fh, "url: " . $url . "\n");
+ if(!empty($data)) fwrite($fh, "data: " . print_r($data, true) . "\n");
+ fwrite($fh, "results:" . print_r($response, true) . "\n");
+ if(!empty($errors)) fwrite($fh, "errors: " . $errors . "\n");
+ fclose($fh);
+ }
}
if($errors) commonModel::$requestErrors[] = $errors;
diff --git a/module/compile/model.php b/module/compile/model.php
index ba7b64cf8e..619de7cf6b 100644
--- a/module/compile/model.php
+++ b/module/compile/model.php
@@ -129,7 +129,14 @@ class compileModel extends model
$url = new stdclass();
$url->userPWD = "$jenkinsUser:$jenkinsPassword";
- $url->url = sprintf('%s/job/%s/buildWithParameters/api/json', $jenkinsServer, $jenkins->pipeline);
+ if(strpos($jenkins->pipeline, '/job/') !== false)
+ {
+ $url->url = sprintf('%s%sbuildWithParameters/api/json', $jenkinsServer, $jenkins->pipeline);
+ }
+ else
+ {
+ $url->url = sprintf('%s/job/%s/buildWithParameters/api/json', $jenkinsServer, $jenkins->pipeline);
+ }
return $url;
}
@@ -261,7 +268,14 @@ class compileModel extends model
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
/* Get build list by API. */
- $url = sprintf('%s/job/%s/api/json?tree=builds[id,number,result,queueId,timestamp]', $jenkins->url, $job->pipeline);
+ if(strpos($job->pipeline, '/job/') !== false)
+ {
+ $url = sprintf('%s%sapi/json?tree=builds[id,number,result,queueId,timestamp]', $jenkins->url, $job->pipeline);
+ }
+ else
+ {
+ $url = sprintf('%s/job/%s/api/json?tree=builds[id,number,result,queueId,timestamp]', $jenkins->url, $job->pipeline);
+ }
$response = common::http($url, '', array(CURLOPT_USERPWD => "$jenkinsUser:$jenkinsPassword"));
if(!$response) return false;
diff --git a/module/gitlab/model.php b/module/gitlab/model.php
index c0052aab6d..8413708a3c 100644
--- a/module/gitlab/model.php
+++ b/module/gitlab/model.php
@@ -20,6 +20,8 @@ class gitlabModel extends model
public $developerAccess = 30;
public $maintainerAccess = 40;
+ protected $projects = array();
+
/**
* Get a gitlab by id.
*
@@ -385,6 +387,45 @@ class gitlabModel extends model
return $branches;
}
+ /**
+ * Get Gitlab commits.
+ *
+ * @param object $repo
+ * @param string $entry
+ * @param string $revision
+ * @param string $type
+ * @param object $pager
+ * @param string $begin
+ * @param string $end
+ * @access public
+ * @return array
+ */
+ public function getCommits($repo, $entry, $revision = 'HEAD', $type = 'dir', $pager = null, $begin = 0, $end = 0)
+ {
+ $scm = $this->app->loadClass('scm');
+ $scm->setEngine($repo);
+ $comments = $scm->engine->getCommitsByPath($entry, '', '', isset($pager->recPerPage) ? $pager->recPerPage : 10, isset($pager->pageID) ? $pager->pageID : 1);
+
+ $designNames = $this->dao->select("commit, name")->from(TABLE_DESIGN)->where('deleted')->eq(0)->fetchPairs();
+ $designIds = $this->dao->select("commit, id")->from(TABLE_DESIGN)->where('deleted')->eq(0)->fetchPairs();
+ $commitIds = array();
+ foreach($comments as $comment)
+ {
+ $comment->revision = $comment->id;
+ $comment->originalComment = $comment->title;
+ $comment->comment = $this->loadModel('repo')->replaceCommentLink($comment->title);
+ $comment->committer = $comment->committer_name;
+ $comment->time = date("Y-m-d H:i:s", strtotime($comment->committed_date));
+ $comment->designName = zget($designNames, $comment->revision, '');
+ $comment->designID = zget($designIds, $comment->revision, '');
+ $commitIds[] = $comment->id;
+ }
+ $commitCounts = $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($commitIds)->fetchPairs();
+ foreach($comments as $comment) $comment->commit = !empty($commitCounts[$comment->id]) ? $commitCounts[$comment->id] : '';
+
+ return $comments;
+ }
+
/**
* Create a gitlab.
*
@@ -424,7 +465,7 @@ class gitlabModel extends model
if(strpos($host, 'http://') !== 0 and strpos($host, 'https://') !== 0) return false;
$url = sprintf($host, $api);
- return json_decode(commonModel::http($url, $data, $options));
+ return json_decode(commonModel::http($url, $data, $options, $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false));
}
/**
@@ -461,7 +502,7 @@ class gitlabModel extends model
$gitlab = $this->loadModel('gitlab')->getByID($gitlabID);
if(!$gitlab) return '';
$url = rtrim($gitlab->url, '/') . "/api/v4/todos?project_id=$projectID&type=MergeRequest&state=pending&private_token={$gitlab->token}&sudo={$sudo}";
- return json_decode(commonModel::http($url));
+ return json_decode(commonModel::http($url, $data = null, $optionsi = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false));
}
/**
@@ -708,7 +749,7 @@ class gitlabModel extends model
$allResults = array();
for($page = 1; true; $page++)
{
- $results = json_decode(commonModel::http($url . "&simple={$simple}&page={$page}&per_page=100"));
+ $results = json_decode(commonModel::http($url . "&simple={$simple}&page={$page}&per_page=100", $data = null, $optionsi = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false));
if(!is_array($results)) break;
if(!empty($results)) $allResults = array_merge($allResults, $results);
if(count($results) < 100) break;
@@ -986,8 +1027,11 @@ class gitlabModel extends model
*/
public function apiGetSingleProject($gitlabID, $projectID)
{
+ if(isset($this->projects[$gitlabID][$projectID])) return $this->projects[$gitlabID][$projectID];
+
$url = sprintf($this->getApiRoot($gitlabID, false), "/projects/$projectID");
- return json_decode(commonModel::http($url));
+ $this->projects[$gitlabID][$projectID] = json_decode(commonModel::http($url, $data = null, $optionsi = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false));
+ return $this->projects[$gitlabID][$projectID];
}
/**
diff --git a/module/jenkins/control.php b/module/jenkins/control.php
index 3bb59632bb..d6e0a4d275 100644
--- a/module/jenkins/control.php
+++ b/module/jenkins/control.php
@@ -125,9 +125,9 @@ class jenkins extends control
*/
public function ajaxGetJenkinsTasks($id)
{
- if(empty($id)) return print(json_encode(array('' => '')));
+ if(empty($id)) return print('');
- $tasks = $this->jenkins->getTasks($id);
- echo json_encode($tasks);
+ $this->view->tasks = $this->jenkins->getTasks($id, 3);
+ $this->display();
}
}
diff --git a/module/jenkins/model.php b/module/jenkins/model.php
index 485e0bf897..4261f464e9 100644
--- a/module/jenkins/model.php
+++ b/module/jenkins/model.php
@@ -51,10 +51,11 @@ class jenkinsModel extends model
* Get jenkins tasks.
*
* @param int $id
+ * @param int $depth
* @access public
* @return array
*/
- public function getTasks($id)
+ public function getTasks($id, $depth = 0)
{
$jenkins = $this->getById($id);
@@ -63,14 +64,67 @@ class jenkinsModel extends model
$jenkinsPassword = $jenkins->token ? $jenkins->token : $jenkins->password;
$userPWD = "$jenkinsUser:$jenkinsPassword";
- $response = common::http($jenkinsServer . '/api/json/items/list', '', array(CURLOPT_USERPWD => $userPWD));
+ $response = common::http($jenkinsServer . '/api/json/items/list' . ($depth ? "?depth=1" : ''), '', array(CURLOPT_USERPWD => $userPWD), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false);
$response = json_decode($response);
$tasks = array();
- if(isset($response->jobs))
+ if($depth)
{
- foreach($response->jobs as $job) $tasks[basename($job->url)] = $job->name;
+ /* Support up to 4 levels. */
+ if(isset($response->jobs)) $tasks = $this->getDepthJobs($response->jobs, $userPWD, 1);
}
+ else
+ {
+ if(isset($response->jobs))
+ {
+ foreach($response->jobs as $job) $tasks[basename($job->url)] = $job->name;
+ }
+ }
+ return $tasks;
+ }
+
+ /**
+ * Get jobs by depth.
+ *
+ * @param object $jobs
+ * @param string $userPWD
+ * @param int $depth
+ * @access protected
+ * @return array
+ */
+ protected function getDepthJobs($jobs, $userPWD, $depth = 1)
+ {
+ if($depth > 4) return array();
+
+ $tasks = array();
+ foreach($jobs as $job)
+ {
+ if(empty($job->url)) continue;
+
+ $isJob = true;
+ if(stripos($job->_class, '.multibranch') !== false or stripos($job->_class, '.folder') !== false or stripos($job->_class, '.OrganizationFolder') !== false) $isJob = false;
+ if(!empty($job->buildable) and $job->buildable == true) $isJob = true;
+
+ if($isJob)
+ {
+ $parms = parse_url($job->url);
+ $tasks[$parms['path']] = $job->name;
+ }
+ else
+ {
+ if($depth > 1)
+ {
+ $response = common::http($job->url . 'api/json', '', array(CURLOPT_USERPWD => $userPWD), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false);
+ $job = json_decode($response);
+ }
+
+ $tasks[basename($job->url)] = array();
+ if(empty($job->jobs)) continue;
+
+ $tasks[basename($job->url)] = $this->getDepthJobs($job->jobs, $userPWD, $depth + 1);
+ }
+ }
+
return $tasks;
}
diff --git a/module/jenkins/view/ajaxgetjenkinstasks.html.php b/module/jenkins/view/ajaxgetjenkinstasks.html.php
new file mode 100644
index 0000000000..a58535289e
--- /dev/null
+++ b/module/jenkins/view/ajaxgetjenkinstasks.html.php
@@ -0,0 +1,96 @@
+
+ * @package repo
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+ $task):?>
+
+
+ -
+
+
+
+ $task2):?>
+
+ -
+
+
+
+ $task3):?>
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
diff --git a/module/job/control.php b/module/job/control.php
index d62d755756..887a53e845 100644
--- a/module/job/control.php
+++ b/module/job/control.php
@@ -60,6 +60,10 @@ class job extends control
$branch = $this->gitlab->apiGetSingleBranch($job->server, $pipeline->project, $pipeline->reference);
if($branch and isset($branch->can_push) and !$branch->can_push) $job->canExec = false;
}
+ elseif($job->engine == 'jenkins')
+ {
+ if(strpos($job->pipeline, '/job/') !== false) $job->pipeline = trim(str_replace('/job/', '/', $job->pipeline), '/');
+ }
}
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->browse;
@@ -115,7 +119,7 @@ class job extends control
}
$this->app->loadLang('action');
- $repoList = $this->loadModel('repo')->getList($this->projectID);
+ $repoList = $this->loadModel('repo')->getList($this->projectID, false);
$repoPairs = array(0 => '');
$gitlabRepos = array(0 => '');
$repoTypes = array();
diff --git a/module/job/css/create.css b/module/job/css/create.css
index 188dd0855c..5c44ac685f 100644
--- a/module/job/css/create.css
+++ b/module/job/css/create.css
@@ -2,9 +2,14 @@
.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;}
+.jktask-label {min-width: 50px; max-width: 300px; border-radius: 0px 4px 4px 0px;}
+.input-group-addon {border-radius: 2px 0px 0px 2px !important;}
+button.text-right {min-width: 100px; text-align: right;}
#server_chosen .chosen-single {border-right: 0px;}
#pipelineBox {width: 385px;}
#svnDirBox .input-group {width: unset !important;}
#jenkinsServerTR .input-group-addon {border-left-width: 0 !important;}
+#jenkinsServerTR .dropdown {position: relative;}
+#jenkinsServerTR .table-col:first-child {width: 375.5px;}
.chosen-container .chosen-drop{z-index: 1100;} /* from c20b7e7a5 */
diff --git a/module/job/js/create.js b/module/job/js/create.js
index cd188907e9..395f47d0cb 100644
--- a/module/job/js/create.js
+++ b/module/job/js/create.js
@@ -18,7 +18,7 @@ $(document).ready(function()
$('#frameBox .loading').remove();
$('#frameBox .input-group').append(html);
$('#frameBox #frame').chosen();
-
+
$('#frame').change();
}
getFrameSelect('');
@@ -171,23 +171,16 @@ $(document).ready(function()
$('#jkServer').change(function()
{
var jenkinsID = $(this).val();
- $('#jenkinsServerTR #jkTask').remove();
- $('#jenkinsServerTR #jkTask_chosen').remove();
+ $('#jenkinsServerTR .dropdown,.input-group-addon').hide();
$('#jenkinsServerTR .input-group').append("");
- $.getJSON(createLink('jenkins', 'ajaxGetJenkinsTasks', 'jenkinsID=' + jenkinsID), function(tasks)
- {
- html = "';
- $('#jenkinsServerTR .loading').remove();
- $('#jenkinsServerTR .input-group').append(html);
+ setJenkinsJob('', '');
- $('#jenkinsServerTR #jkTask').chosen({drop_direction: 'auto'});
- })
+ $.get(createLink('jenkins', 'ajaxGetJenkinsTasks', 'jenkinsID=' + jenkinsID), function(tasks)
+ {
+ $('#jenkinsServerTR .loading').remove();
+ $('#dropMenuTasks').html(tasks);
+ $('#jenkinsServerTR .dropdown,.input-group-addon').show();
+ });
/* There has been a problem with handling the prompt label. */
$('#jkTaskLabel').remove();
@@ -253,3 +246,18 @@ $(document).ready(function()
$('#engine').change();
$('#triggerType').change();
});
+
+/**
+ * Set jenkins job.
+ *
+ * @param string $name
+ * @param string $task
+ * @access public
+ * @return void
+ */
+function setJenkinsJob(name, task)
+{
+ if(name) $('.jktask-label').removeClass('text-right');
+ $('#jkTask').val(task);
+ $('.jktask-label .text').html(name);
+}
diff --git a/module/job/view/create.html.php b/module/job/view/create.html.php
index 13b7ee4f2b..ccdb62f149 100644
--- a/module/job/view/create.html.php
+++ b/module/job/view/create.html.php
@@ -106,13 +106,17 @@
| job->jkHost; ?> |
-
+ |
diff --git a/module/mr/control.php b/module/mr/control.php
index 173d7c0261..7d2e34b035 100644
--- a/module/mr/control.php
+++ b/module/mr/control.php
@@ -34,16 +34,38 @@ class mr extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
- $repos = $this->loadModel('repo')->getListBySCM(array('Gitlab', 'Gitea', 'Gogs'));
- if(empty($repos)) $this->locate($this->repo->createLink('create'));
+ $repoCount = $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0')
+ ->andWhere('SCM')->in(array('Gitlab', 'Gitea', 'Gogs'))
+ ->andWhere('synced')->eq(1)
+ ->orderBy('id')
+ ->count();
+ if($repoCount == 0) $this->locate($this->repo->createLink('create'));
- $repoID = $this->repo->saveState($repoID, $objectID);
+ $repoID = $this->loadModel('repo')->saveState($repoID, $objectID);
$repo = $this->repo->getRepoByID($repoID);
- if(!in_array(strtolower($repo->SCM), $this->config->mr->gitServiceList)) $repo = $repos[0];
+ if(!in_array(strtolower($repo->SCM), $this->config->mr->gitServiceList))
+ {
+ $repoID = $this->dao->select('id')->from(TABLE_REPO)->where('deleted')->eq('0')->andWhere('SCM')->in(array('Gitlab', 'Gitea', 'Gogs'))->andWhere('synced')->eq(1)->orderBy('id')->fetch('id');
+ $repo = $this->repo->getRepoByID($repoID);
+ }
$this->loadModel('ci')->setMenu($repo->id);
- $projects = $this->mr->getAllProjects($repoID, $repo->SCM);
- $MRList = $this->mr->getList($mode, $param, $orderBy, $pager, empty($projects) ? false : $projects, $repoID);
+ $filterProjects = empty($repo->serviceProject) ? array() : array($repo->serviceHost => array($repo->serviceProject => $repo->serviceProject));
+ $MRList = $this->mr->getList($mode, $param, $orderBy, $pager, $filterProjects, $repoID);
+ if($repo->SCM == 'Gitlab')
+ {
+ $projectIds = array();
+ foreach($MRList as $MR)
+ {
+ $projectIds[$MR->sourceProject] = $MR->sourceProject;
+ $projectIds[$MR->targetProject] = $MR->targetProject;
+ }
+ $projects = $this->mr->getGitlabProjects($repo->serviceHost, $projectIds);
+ }
+ else
+ {
+ $projects = $this->mr->getAllProjects($repoID, $repo->SCM);
+ }
/* Save current URI to session. */
$this->session->set('mrList', $this->app->getURI(true), 'repo');
@@ -87,7 +109,6 @@ class mr extends control
$this->view->param = $param;
$this->view->repoID = $repoID;
$this->view->objectID = $objectID;
- $this->view->repos = $repos;
$this->view->repo = $repo;
$this->view->orderBy = $orderBy;
$this->view->openIDList = $openIDList;
diff --git a/module/mr/model.php b/module/mr/model.php
index 2d06fe1ad9..178d87a02a 100644
--- a/module/mr/model.php
+++ b/module/mr/model.php
@@ -143,10 +143,11 @@ class mrModel extends model
* Get gitlab projects.
*
* @param int $hostID
+ * @param array $projectIds
* @access public
* @return array
*/
- public function getGitlabProjects($hostID = 0)
+ public function getGitlabProjects($hostID = 0, $projectIds = array())
{
$allProjects = array();
$allGroups = array();
@@ -164,7 +165,19 @@ class mrModel extends model
$minProject = min($projectCount->minSource, $projectCount->minTarget);
$maxProject = max($projectCount->maxSource, $projectCount->maxTarget);
}
- $allProjects[$hostID] = $this->gitlab->apiGetProjects($hostID, 'false', $minProject, $maxProject);
+
+ if($projectIds)
+ {
+ foreach($projectIds as $projectID)
+ {
+ $project = $this->gitlab->apiGetSingleProject($hostID, $projectID);
+ if(isset($project->id)) $allProjects[$hostID][] = $project;
+ }
+ }
+ else
+ {
+ $allProjects[$hostID] = $this->gitlab->apiGetProjects($hostID, 'false', $minProject, $maxProject);
+ }
/* If not an administrator, need to obtain group member information. */
$groupIDList = array(0 => 0);
@@ -747,7 +760,7 @@ class mrModel extends model
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls");
}
- $response = json_decode(commonModel::http($url));
+ $response = json_decode(commonModel::http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data', $method = 'POST', $timeout = 30, $httpCode = false, $log = false));
if(empty($response)) $response = array();
if($scm == 'Gitea')
{
diff --git a/module/repo/control.php b/module/repo/control.php
index 5b125ab8e9..32ea458c9f 100644
--- a/module/repo/control.php
+++ b/module/repo/control.php
@@ -80,7 +80,7 @@ class repo extends control
$repoID = $this->repo->saveState(0, $objectID);
if($this->viewType !== 'json') $this->commonAction($repoID, $objectID);
- $repoList = $this->repo->getList(0, '', $orderBy);
+ $repoList = $this->repo->getList(0, '', $orderBy, null, true);
$sonarRepoList = $this->loadModel('job')->getSonarqubeByRepo(array_keys($repoList));
/* Pager. */
@@ -599,17 +599,48 @@ class repo extends control
}
/* Refresh repo. */
- if($refresh) $this->repo->updateCommit($repoID, $objectID, $originBranchID);
+ if($refresh)
+ {
+ $this->repo->updateCommit($repoID, $objectID, $originBranchID);
- /* Get files info. */
- $infos = $this->repo->getFileCommits($repo, $branchID, $path);
- if($this->cookie->repoRefresh) setcookie('repoRefresh', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
+ if($repo->SCM == 'Gitlab') $this->repo->checkDeletedBranches($repoID, $branches);
+ }
/* Set logType and revisions. */
$logType = 'dir';
$revisions = $this->repo->getCommits($repo, $path, $revision, $logType, $pager);
$lastRevision = current($revisions);
+ /* Get files info. */
+ if($repo->SCM == 'Gitlab')
+ {
+ $cacheFile = $this->repo->getCacheFile($repo->id, $path, $branchID);
+ $cacheRefreshTime = isset($lastRevision->time) ? date('Y-m-d H:i', strtotime($lastRevision->time)) : date('Y-m-d H:i');
+ if(!$cacheFile or !file_exists($cacheFile) or filemtime($cacheFile) < strtotime($cacheRefreshTime))
+ {
+ $infos = $this->repo->getFileList($repo, $branchID, $path);
+
+ if($cacheFile)
+ {
+ if(!file_exists($cacheFile . '.lock'))
+ {
+ touch($cacheFile . '.lock');
+ file_put_contents($cacheFile, serialize($infos));
+ unlink($cacheFile . '.lock');
+ }
+ }
+ }
+ else
+ {
+ $infos = unserialize(file_get_contents($cacheFile));
+ }
+ }
+ else
+ {
+ $infos = $this->repo->getFileCommits($repo, $branchID, $path);
+ }
+ if($this->cookie->repoRefresh) setcookie('repoRefresh', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
+
/* Synchronous commit only in root path. */
if(in_array($repo->SCM, $this->config->repo->gitTypeList) and empty($path) and $infos and empty($revisions)) $this->locate($this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID&branch=" . helper::safe64Encode(base64_encode($this->cookie->repoBranch))));
@@ -685,6 +716,8 @@ class repo extends control
$this->view->revision = $revision;
$this->view->repoID = $repoID;
$this->view->objectID = $objectID;
+ $this->view->entry = $entry;
+ $this->view->type = $type;
$this->view->branchID = $this->cookie->repoBranch;
$this->view->entry = urldecode($entry);
$this->view->path = urldecode($entry);
diff --git a/module/repo/css/log.css b/module/repo/css/log.css
index 841e94940e..dce12717c7 100644
--- a/module/repo/css/log.css
+++ b/module/repo/css/log.css
@@ -1 +1,2 @@
.m-repo-log .btn-back {margin-right: 0; padding-top: 8px;}
+#repoPageSize {right: 30px;}
diff --git a/module/repo/js/log.js b/module/repo/js/log.js
index 45fccf07ca..e403a9a9d5 100644
--- a/module/repo/js/log.js
+++ b/module/repo/js/log.js
@@ -13,7 +13,7 @@ function processCheckbox()
if (checkNum >= 2)
{
$("input:checkbox[name='revision[]']").each(function(){if($(this).attr('checked') == false) $(this).attr("disabled","disabled")});
- }
+ }
else
{
$("input:checkbox[name='revision[]']").each(function(){if($(this).attr('checked') == false) $(this).attr("enabled","enabled")});
diff --git a/module/repo/model.php b/module/repo/model.php
index 3a9aa88859..c3717e9890 100644
--- a/module/repo/model.php
+++ b/module/repo/model.php
@@ -107,10 +107,11 @@ class repoModel extends model
* @param string $SCM Subversion|Git|Gitlab
* @param string $orderBy
* @param object $pager
+ * @param bool $getCodePath
* @access public
* @return array
*/
- public function getList($projectID = 0, $SCM = '', $orderBy = 'id_desc', $pager = null)
+ public function getList($projectID = 0, $SCM = '', $orderBy = 'id_desc', $pager = null, $getCodePath = false)
{
$repos = $this->dao->select('*')->from(TABLE_REPO)
->where('deleted')->eq('0')
@@ -143,7 +144,7 @@ class repoModel extends model
}
}
- if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo);
+ if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo, $getCodePath);
}
return $repos;
@@ -731,6 +732,8 @@ class repoModel extends model
*/
public function getCommits($repo, $entry, $revision = 'HEAD', $type = 'dir', $pager = null, $begin = 0, $end = 0)
{
+ if($repo->SCM == 'Gitlab') return $this->loadModel('gitlab')->getCommits($repo, $entry, $revision, $type, $pager, $begin, $end);
+
$entry = ltrim($entry, '/');
$entry = $repo->prefix . (empty($entry) ? '' : '/' . $entry);
@@ -895,10 +898,10 @@ class repoModel extends model
*/
public function getCacheFile($repoID, $path, $revision)
{
- $cachePath = $this->app->getCacheRoot() . '/' . 'repo';
+ $cachePath = $this->app->getCacheRoot() . '/repo/' . $repoID;
if(!is_dir($cachePath)) mkdir($cachePath, 0777, true);
if(!is_writable($cachePath)) return false;
- return $cachePath . '/' . $repoID . '-' . md5("{$this->cookie->repoBranch}-$path-$revision");
+ return $cachePath . '/' . md5("{$this->cookie->repoBranch}-$path-$revision");
}
/**
@@ -2136,20 +2139,21 @@ class repoModel extends model
* Process git service repo.
*
* @param object $repo
+ * @param bool $getCodePath
* @access public
* @return object
*/
- public function processGitService($repo)
+ public function processGitService($repo, $getCodePath = true)
{
$service = $this->loadModel('pipeline')->getByID($repo->serviceHost);
if($repo->SCM == 'Gitlab')
{
- $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject);
+ if($getCodePath) $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject);
$repo->path = $service ? sprintf($this->config->repo->{$service->type}->apiPath, $service->url, $repo->serviceProject) : '';
$repo->client = $service ? $service->url : '';
$repo->password = $service ? $service->token : '';
- $repo->codePath = $project ? $project->web_url : $repo->path;
+ $repo->codePath = isset($project->web_url) ? $project->web_url : $repo->path;
}
elseif(in_array($repo->SCM, array('Gitea', 'Gogs')))
{
@@ -2368,6 +2372,48 @@ class repoModel extends model
return array_merge($folders, $files);
}
+ /**
+ * Get Repo file list.
+ *
+ * @param object $repo
+ * @param string $branch
+ * @param string $path
+ * @access public
+ * @return array
+ */
+ public function getFileList($repo, $branch, $path = '')
+ {
+ $scm = $this->app->loadClass('scm');
+ $scm->setEngine($repo);
+
+ $paths = array();
+ $files = $scm->engine->tree($path, 0);
+ foreach($files as $file)
+ {
+ $paths[] = $file->path;
+ }
+
+ $requests = array();
+ foreach($paths as $path)
+ {
+ $requests[]['url'] = $scm->engine->getCommitsByPath($path, '', '', 1, 1, true);
+ }
+ $this->app->loadClass('requests', true);
+ $commits = requests::request_multiple($requests);
+
+ foreach($files as $key => $file)
+ {
+ $files[$key]->kind = $file->type == 'tree' ? 'dir' : 'file';
+
+ $commit = isset($commits[$key]->body) ? json_decode($commits[$key]->body) : array();
+ $files[$key]->revision = isset($commit[0]->id) ? $commit[0]->id : '';
+ $files[$key]->comment = isset($commit[0]->title) ? $commit[0]->title : '';
+ $files[$key]->account = isset($commit[0]->committer_name) ? $commit[0]->committer_name : '';
+ $files[$key]->date = isset($commit[0]->committed_date) ? $commit[0]->committed_date : '';
+ }
+ return $files;
+ }
+
/**
* Get html for file tree.
*
@@ -2383,6 +2429,50 @@ class repoModel extends model
$allFiles = array();
if(is_null($diffs))
{
+ if($repo->SCM == 'Gitlab')
+ {
+ $cacheFile = $this->getCacheFile($repo->id, 'tree-list', 'tree-list');
+ $lastRevision = $this->dao->select('t1.revision')->from(TABLE_REPOHISTORY)->alias('t1')
+ ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
+ ->where('t1.repo')->eq($repo->id)
+ ->andWhere('t2.branch')->eq($this->cookie->repoBranch)
+ ->orderBy('t1.commit desc')
+ ->fetch('revision');
+
+ if($cacheFile and file_exists($cacheFile)) $infos = unserialize(file_get_contents($cacheFile));
+ if(!$cacheFile or !file_exists($cacheFile) or $infos['revision'] != $lastRevision)
+ {
+ $scm = $this->app->loadClass('scm');
+ $scm->setEngine($repo);
+
+ $this->app->loadClass('requests', true);
+ $files = $scm->engine->tree('', 1, true);
+
+ $allFiles = array();
+ foreach($files as $file)
+ {
+ $allFiles[] = $file->path;
+ }
+ $infos = array('revision' => $lastRevision, 'files' => $allFiles);
+
+ if($cacheFile)
+ {
+ if(!file_exists($cacheFile . '.lock'))
+ {
+ touch($cacheFile . '.lock');
+ file_put_contents($cacheFile, serialize($infos));
+ unlink($cacheFile . '.lock');
+ }
+ }
+ }
+ else
+ {
+ $infos = unserialize(file_get_contents($cacheFile));
+ $allFiles = $infos['files'];
+ }
+ }
+ else
+ {
if($repo->SCM != 'Subversion' and empty($branch)) $branch = $this->cookie->repoBranch;
$files = $this->dao->select('t1.path,t2.time,t1.action')->from(TABLE_REPOFILES)->alias('t1')
->leftJoin(TABLE_REPOHISTORY)->alias('t2')->on('t1.revision=t2.id')
@@ -2420,6 +2510,7 @@ class repoModel extends model
$allFiles[] = $file->path;
}
}
+ }
}
else
{
@@ -2834,4 +2925,33 @@ class repoModel extends model
}
if($repo->SCM == 'Subversion') $this->loadModel('svn')->updateCommit($repo, $commentGroup, false);
}
+
+ /**
+ * Delete the deleted branch.
+ *
+ * @param int $repoID
+ * @param array $latestBranches
+ * @access public
+ * @return bool
+ */
+ public function checkDeletedBranches($repoID, $latestBranches)
+ {
+ if(empty($latestBranches)) return false;
+
+ $currentBranches = $this->dao->select('branch')->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->groupBy('branch')->fetchPairs('branch');
+
+ $deletedBranches = array_diff($currentBranches, $latestBranches);
+ foreach($deletedBranches as $deletedBranch)
+ {
+ if($deletedBranch == 'master') continue;
+
+ $revisionIds = $this->dao->select('revision')->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->andWhere('branch')->eq($deletedBranch)->fetchPairs('revision');
+ $fileIds = $this->dao->select('id')->from(TABLE_REPOFILES)->where('revision')->in($revisionIds)->fetchPairs('id');
+
+ $this->dao->delete()->from(TABLE_REPOHISTORY)->where('id')->in($revisionIds)->exec();
+ $this->dao->delete()->from(TABLE_REPOFILES)->where('id')->in($fileIds)->exec();
+ $this->dao->delete()->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->andWhere('branch')->eq($deletedBranch)->exec();
+ }
+ return true;
+ }
}
diff --git a/module/repo/view/:w b/module/repo/view/:w
new file mode 100644
index 0000000000..25441d5bb5
--- /dev/null
+++ b/module/repo/view/:w
@@ -0,0 +1,104 @@
+
+
+
+repo->encodePath($entry) . "&revision=$revision&type=$type");?>
+
+
+
+
+
+
+
diff --git a/module/repo/view/log.html.php b/module/repo/view/log.html.php
index 290400edb4..6e0ae614a0 100644
--- a/module/repo/view/log.html.php
+++ b/module/repo/view/log.html.php
@@ -10,6 +10,7 @@
?>
+repo->encodePath($entry) . "&revision=$revision&type=$type");?>
" . $lang->goback, '', 'btn btn-link');?>
@@ -81,7 +82,15 @@
|