Merge branch 'gitlab_optimize' into 'master'

Gitlab optimize

See merge request easycorp/zentaopms!7148
This commit is contained in:
王怡栋
2023-03-09 08:05:10 +00:00
19 changed files with 684 additions and 95 deletions
+69 -17
View File
@@ -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;
}
+30 -23
View File
@@ -3181,18 +3181,21 @@ EOD;
curl_close($curl);
$logFile = $app->getLogRoot() . 'saas.'. date('Ymd') . '.log.php';
if(!file_exists($logFile)) file_put_contents($logFile, '<?php die(); ?' . '>');
$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, '<?php die(); ?' . '>');
$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, '<?php die(); ?' . '>');
$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, '<?php die(); ?' . '>');
$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;
+16 -2
View File
@@ -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;
+48 -4
View File
@@ -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];
}
/**
+3 -3
View File
@@ -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();
}
}
+58 -4
View File
@@ -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;
}
@@ -0,0 +1,96 @@
<?php
/**
* The jenkins task view file of repo module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license LGPL (http://www.gnu.org/licenses/lgpl.html)
* @author Gang Zeng <zenggang@cnezsoft.com>
* @package repo
* @version $Id$
* @link http://www.zentao.net
*/
?>
<style>
#dropMenuTasks .tree li {padding: 3px 0 0 10px;}
#dropMenuTasks .tree li.has-list.open:before {border-left: 0px;}
#dropMenuTasks .tree li > a {max-width: 100%; line-height: 20px; border-radius: 2px; padding-top: 5px;}
#dropMenuTasks .col-left {padding: 0;}
#dropMenuTasks .label {margin-left: 3px;}
#dropMenuTasks .hide-in-search {padding-left: 8px;}
#dropMenuTasks .hide-in-search .hidden {display: block !important; visibility: inherit !important;}
#dropMenuTasksRepo > div.table-row > div > div > ul > li > div {padding-left: 10px;}
#dropMenuTasks ul.tree-angles {margin-bottom: 0;}
#dropMenuTasks {margin: 0;}
#dropMenuTasks ul > li > ul > li > a:hover {color: white; background-color: #0c64eb; text-decoration: none;}
#dropMenuTasks .tree .has-list > ul > li {padding-top: 0;}
.search-list .list-group {padding: 7px 10px;}
#dropMenuTasks .label-type {margin: 1px 10px; line-height: 20px;}
.tree li>.list-toggle {top: 0px;}
.tree .one-level>.list-toggle {top: 3px;}
</style>
<div class="table-row">
<div class="table-col col-left">
<div class="list-group" id="jenkinsTaskList">
<ul class='tree tree-angles' data-ride='tree' data-idx='0'>
<?php foreach($tasks as $groupName => $task):?>
<?php if(empty($task)) continue;?>
<?php if(is_array($task)):?>
<li data-idx='$groupName' data-id='<?php echo $groupName?>' class='has-list open in one-level'>
<i class='list-toggle icon'></i>
<div class='label-type'>
<a class='text-muted not-list-item'><?php echo $groupName;?></a>
</div>
<ul data-idx='<?php echo $groupName;?>'>
<?php foreach($task as $task2name => $task2):?>
<?php if(is_array($task2)):?>
<li data-idx='$groupName' data-id='<?php echo $task2name?>' class='has-list open in'>
<i class='list-toggle icon'></i>
<div class='label-type'>
<a class='text-muted not-list-item'><?php echo $task2name;?></a>
</div>
<ul data-idx='<?php echo $task2name;?>'>
<?php foreach($task2 as $task3name => $task3):?>
<?php if(is_array($task3)):?>
<li data-idx='$groupName' data-id='<?php echo $task3name?>' class='has-list open in'>
<i class='list-toggle icon'></i>
<div class='label-type'>
<a class='text-muted not-list-item'><?php echo $task3name;?></a>
</div>
<ul data-idx='<?php echo $task3name;?>'>
<?php foreach($task3 as $task4name => $task4):?>
<?php if(is_array($task4)) continue;?>
<li data-idx='<?php echo $task4name;?>' data-id='<?php echo $task4name;?>'>
<a href='###' id='<?php echo $task4name?>' class='' text-ellipsis' onclick='setJenkinsJob("<?php echo $task4;?>","<?php echo $task4name;?>")' title='<?php echo $task4;?>' data-key='<?php echo $task4;?>'><?php echo $task4;?></a>
</li>
<?php endforeach;?>
</ul>
</li>
<?php else:?>
<li data-idx='<?php echo $task3name;?>' data-id='<?php echo $task3name;?>'>
<a href='###' id='<?php echo $task3name?>' onclick='setJenkinsJob("<?php echo $task3;?>","<?php echo $task3name;?>")' class='' text-ellipsis' title='<?php echo $task3;?>' data-key='<?php echo $task3;?>'><?php echo $task3;?></a>
</li>
<?php endif;?>
<?php endforeach;?>
</ul>
</li>
<?php else:?>
<li data-idx='<?php echo $task2name;?>' data-id='<?php echo $task2name;?>'>
<a href='###' onclick='setJenkinsJob("<?php echo $task2;?>","<?php echo $task2name;?>")' id='<?php echo $task2name?>' class='' text-ellipsis' title='<?php echo $task2;?>' data-key='<?php echo $task2;?>'><?php echo $task2;?></a>
</li>
<?php endif;?>
<?php endforeach;?>
</ul>
</li>
<?php else:?>
<li data-idx='<?php echo $task;?>' data-id='<?php echo $task;?>'>
<a href='###' id='<?php echo $task;?>' class='text-ellipsis' onclick='setJenkinsJob("<?php echo $task;?>","<?php echo $groupName;?>")' title='<?php echo $task;?>' data-key='<?php echo $task;?>' ><?php echo $task;?></a>
</li>
<?php endif;?>
<?php endforeach;?>
</ul>
</div>
</div>
</div>
<script>
$('#jenkinsTaskList .tree').tree();
</script>
+5 -1
View File
@@ -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();
+5
View File
@@ -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 */
+24 -16
View File
@@ -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("<div class='load-indicator loading'></div>");
$.getJSON(createLink('jenkins', 'ajaxGetJenkinsTasks', 'jenkinsID=' + jenkinsID), function(tasks)
{
html = "<select id='jkTask' name='jkTask' class='form-control'>";
for(taskKey in tasks)
{
var task = tasks[taskKey];
html += "<option value='" + taskKey + "'>" + task + "</option>";
}
html += '</select>';
$('#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);
}
+6 -2
View File
@@ -106,13 +106,17 @@
</tr>
<tr id="jenkinsServerTR">
<th><?php echo $lang->job->jkHost; ?></th>
<td colspan='2' class='required'>
<td colspan='2'>
<div class='table-row'>
<div class='table-col'><?php echo html::select('jkServer', $jenkinsServerList, '', "class='form-control chosen'"); ?></div>
<div class='table-col'>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->job->pipeline;?></span>
<?php echo html::select('jkTask', array('' => ''), '', "class='form-control chosen'"); ?>
<div class='dropdown'>
<?php echo html::hidden('jkTask');?>
<button data-toggle='dropdown' type='button' class='btn jktask-label required text-right' title=''><span class='text'></span> <span class='caret' style='margin-bottom: -1px'></span></button>
<div id='dropMenuTasks' class='dropdown-menu search-list' data-ride='searchList' data-url=''></div>
</div>
</div>
</div>
</div>
+28 -7
View File
@@ -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;
+16 -3
View File
@@ -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')
{
+38 -5
View File
@@ -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);
+1
View File
@@ -1 +1,2 @@
.m-repo-log .btn-back {margin-right: 0; padding-top: 8px;}
#repoPageSize {right: 30px;}
+1 -1
View File
@@ -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")});
+127 -7
View File
@@ -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;
}
}
+104
View File
@@ -0,0 +1,104 @@
<?php
/**
* The log view file of repo module of ZenTaoPMS.
*
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
* @author Wang Yidong, Zhu Jinyong
* @package repo
* @version $Id: log.html.php $
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('repoID', $repoID);?>
<?php js::set('paramsBase', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($entry) . "&revision=$revision&type=$type");?>
<div id='mainMenu' class='clearfix'>
<div class="btn-toolbar pull-left">
<?php 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('log', "repoID=$repoID&objectID=$objectID"), $repo->name, '', "data-app='{$app->tab}'");
$paths= explode('/', $entry);
$fileName = array_pop($paths);
$postPath = '';
foreach($paths as $pathName)
{
$postPath .= $pathName . '/';
echo '/' . ' ' . html::a($this->repo->createLink('log', "repoID=$repoID&ojbectID=$objectID&entry=" . $this->repo->encodePath($postPath)), trim($pathName, '/'), '', "data-app='{$app->tab}'");
}
echo '/' . ' ' . $fileName;
?>
</strong>
</div>
</div>
</div>
<div id="mainContent">
<nav id="contentNav">
<ul class="nav nav-default">
<?php $encodeEntry = $this->repo->encodePath($entry);?>
<li><a><?php echo $lang->repo->log;?></a></li>
<li><?php echo html::a($this->repo->createLink('view', "repoID=$repoID&objectID=$objectID&entry=$encodeEntry&revision=$revision"), $lang->repo->view, '', "data-app='{$app->tab}'");?></li>
<?php if($info->kind == 'file'):?>
<li><?php echo html::a($this->repo->createLink('blame', "repoID=$repoID&objectID=$objectID&entry=$encodeEntry&revision=$revision"), $lang->repo->blame, '', "data-app='{$app->tab}'");?></li>
<li><?php echo html::a($this->repo->createLink('download', "repoID=$repoID&path=$encodeEntry&fromRevision=$revision"), $lang->repo->download, 'hiddenwin');?></li>
<?php endif;?>
</ul>
</nav>
<form id='logForm' class='main-table' data-ride='table' method='post'>
<table class='table table-fixed' id='logList'>
<thead>
<tr>
<th class='w-40px'></th>
<th class='w-110px'><?php echo $lang->repo->revision?></th>
<?php if($repo->SCM != 'Subversion'):?>
<th class='w-90px'><?php echo $lang->repo->commit?></th>
<?php endif;?>
<th class='w-150px'><?php echo $lang->repo->date?></th>
<th class='w-100px'><?php echo $lang->repo->committer?></th>
<th><?php echo $lang->repo->comment?></th>
</tr>
</thead>
<tbody>
<?php foreach($logs as $log):?>
<tr>
<td>
<div class='checkbox-primary'>
<input type='checkbox' name='revision[]' value="<?php echo $log->revision?>" />
<label></label>
</div>
</td>
<td class='versions'><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision=" . $log->revision), substr($log->revision, 0, 10), '', "data-app='{$app->tab}'");?></td>
<?php if($repo->SCM != 'Subversion'):?>
<td><?php echo $log->commit?></td>
<?php endif;?>
<td><?php echo $log->time;?></td>
<td><?php echo $log->committer;?></td>
<td class='comment'><?php echo $log->comment;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<?php if(common::hasPriv('repo', 'diff')) echo html::submitButton($lang->repo->diff, '', count($logs) < 2 ? 'disabled btn btn-primary' : 'btn btn-primary')?>
<?php if($repo->SCM == 'Gitlab'):?>
<?php
$prePage = $pager->pageID == 1 ? 1 : $pager->pageID - 1;
$nextPage = $pager->pageID == $pager->pageTotal ? $pager->pageID : $pager->pageID + 1;
$params = "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($entry) . "&revision=$revision&type=$type&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";
$preLink = $this->repo->createLink('log', "$params&pageID=$prePage");
$nextLink = $this->repo->createLink('log', "$params&pageID=$nextPage");
//echo html::a($preLink, "<i class='icon icon-angle-left'></i>", "", "" . ($prePage == $pager->pageID ? ' disabled' : ''));
//echo html::a($nextLink, "<i class='icon icon-angle-right'></i>", "", "" . ($nextPage == $pager->pageID ? ' disabled' : ''));
$total = count($logs) < $pager->recPerPage ? $pager->recPerPage * $pager->pageID : $pager->recPerPage * ($pager->pageID + 1)
?>
<ul id="repoPageSize" class="pager" data-ride="pager" data-elements="size_menu,prev_icon,next_icon" data-rec-total="<?php echo $total;?>" data-rec-per-page="<?php echo $pager->recPerPage;?>" data-page="<?php echo $pager->pageID;?>" data-link-creator="<?php echo $this->repo->createLink('log', $params . '&pageID={page}');?>"></ul>
<?php else:?>
<?php $pager->show('right', 'pagerjs');?>
<?php endif;?>
</div>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+9
View File
@@ -10,6 +10,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('repoID', $repoID);?>
<?php js::set('paramsBase', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($entry) . "&revision=$revision&type=$type");?>
<div id='mainMenu' class='clearfix'>
<div class="btn-toolbar pull-left">
<?php echo html::backButton("<i class='icon icon-back icon-sm'></i> " . $lang->goback, '', 'btn btn-link');?>
@@ -81,7 +82,15 @@
</table>
<div class='table-footer'>
<?php if(common::hasPriv('repo', 'diff')) echo html::submitButton($lang->repo->diff, '', count($logs) < 2 ? 'disabled btn btn-primary' : 'btn btn-primary')?>
<?php if($repo->SCM == 'Gitlab'):?>
<?php
$params = "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($entry) . "&revision=$revision&type=$type&recTotal={$pager->recTotal}";
$total = count($logs) < $pager->recPerPage ? $pager->recPerPage * $pager->pageID : $pager->recPerPage * ($pager->pageID + 1)
?>
<ul id="repoPageSize" data-page-cookie='pagerRepoLog' class="pager" data-ride="pager" data-elements="size_menu,prev_icon,next_icon" data-rec-total="<?php echo $total;?>" data-rec-per-page="<?php echo $pager->recPerPage;?>" data-page="<?php echo $pager->pageID;?>" data-link-creator="<?php echo $this->repo->createLink('log', $params . '&recPerPage={recPerPage}&pageID={page}');?>"></ul>
<?php else:?>
<?php $pager->show('right', 'pagerjs');?>
<?php endif;?>
</div>
</form>
</div>