diff --git a/db/update17.3.sql b/db/update17.3.sql index 8a2671fe3c..e27fcd7259 100644 --- a/db/update17.3.sql +++ b/db/update17.3.sql @@ -2,6 +2,10 @@ ALTER TABLE `zt_mr` CHANGE COLUMN `gitlabID` `hostID` mediumint(8) UNSIGNED NOT ALTER TABLE `zt_mr` MODIFY COLUMN `sourceProject` varchar(50) NOT NULL AFTER `hostID`; ALTER TABLE `zt_mr` MODIFY COLUMN `targetProject` varchar(50) NOT NULL AFTER `sourceBranch`; UPDATE `zt_project` SET `status`='closed' WHERE `type` IN ('sprint', 'stage', 'kanban') AND `model`='' AND `status` = 'done'; +ALTER TABLE `zt_repo` ADD COLUMN `serviceHost` varchar(50) NOT NULL AFTER `client`; +ALTER TABLE `zt_repo` ADD COLUMN `serviceProject` varchar(100) NOT NULL AFTER `serviceHost`; +UPDATE `zt_repo` SET `serviceHost` = `client`, `serviceProject` = `path` WHERE `SCM` = 'Gitlab'; +UPDATE `zt_repo` SET `client` = '', `path` = '' WHERE `SCM` = 'Gitlab'; UPDATE `zt_workflowfield` SET `options`='user' WHERE `buildin`='1' AND `options`='8'; INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES @@ -9,4 +13,4 @@ INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `nam ('testcase', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 4, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), ('task', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 4, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), ('bug', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 6, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), -('build', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 5, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'); +('build', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 5, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'); \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index ad5feb37ee..c0af747c5d 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -1257,6 +1257,8 @@ CREATE TABLE IF NOT EXISTS `zt_repo` ( `encoding` varchar(20) NOT NULL, `SCM` varchar(10) NOT NULL, `client` varchar(100) NOT NULL, + `serviceHost` varchar(50) NOT NULL, + `serviceProject` varchar(100) NOT NULL, `commits` mediumint(8) unsigned NOT NULL, `account` varchar(30) NOT NULL, `password` varchar(30) NOT NULL, diff --git a/lib/scm/gitea.class.php b/lib/scm/gitea.class.php index 1585de2822..26a1b3a3b9 100644 --- a/lib/scm/gitea.class.php +++ b/lib/scm/gitea.class.php @@ -1,27 +1,30 @@ client = $client; - $this->root = rtrim($root, '/') . '/'; - $this->token = $password; - $this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : 'HEAD'; + $this->root = rtrim($root, DIRECTORY_SEPARATOR); + $this->branch = isset($_COOKIE['repoBranch']) ? 'origin/' . $_COOKIE['repoBranch'] : ''; + + chdir($this->root); + exec("{$this->client} config core.quotepath false"); } /** @@ -35,50 +38,48 @@ class gitea public function ls($path, $revision = 'HEAD') { if(!scm::checkRevision($revision)) return array(); - $api = "contents"; - $path = ltrim($path, '/'); - if($path) $api .= "/$path"; - $param = new stdclass(); - $param->ref = $revision; - $param->recursive = 0; - if(!empty($this->branch)) $param->ref = $this->branch; + $path = ltrim($path, DIRECTORY_SEPARATOR); + $sub = ''; + chdir($this->root); + if(!empty($path)) $sub = ":$path"; + if(!empty($this->branch))$revision = $this->branch; + $cmd = escapeCmd("$this->client ls-tree -l $revision$sub"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); - $list = $this->fetch($api, $param, true); - if(empty($list)) return array(); - - $infos = array(); - foreach($list as $file) + $infos = array(); + foreach($list as $entry) { - if(!isset($file->type)) continue; + list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry); - $info = new stdClass(); - $info->name = $file->name; - $info->kind = $file->type; + /* Get commit info. */ + $pathName = ltrim($path . DIRECTORY_SEPARATOR . $name, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client log -1 $this->branch -- $pathName"); + $commit = execCmd($cmd, 'array'); + $logs = $this->parseLog($commit); - if($file->type == 'file') + if($size > 1024 * 1024) { - $file = $this->files($file->path, $this->branch); - - $info->revision = zget($file, 'revision', ''); - $info->comment = zget($file, 'comment', ''); - $info->account = zget($file, 'committer', ''); - $info->date = zget($file, 'date', ''); - $info->size = zget($file, 'size', ''); + $size = round($size / (1024 * 1024), 2) . 'MB'; + } + else if($size > 1024) + { + $size = round($size / 1024, 2) . 'KB'; } else { - $commits = $this->getCommitsByPath($file->path, '', '', 1, 1); - if(empty($commits) or !is_array($commits)) continue; - $commit = $commits[0]; - - $info->revision = $commit->sha; - $info->comment = $commit->commit->message; - $info->account = $commit->commit->author->name; - $info->date = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); - $info->size = 0; + $size .= 'Bytes'; } + $info = new stdClass(); + $info->name = $name; + $info->kind = $kind == 'tree' ? 'dir' : 'file'; + $info->revision = $logs ? $logs[0]->revision : $revision; + $info->size = $size; + $info->account = $logs ? $logs[0]->committer : ''; + $info->date = $logs ? $logs[0]->time : ''; + $info->comment = $logs ? $logs[0]->comment : ''; $infos[] = $info; unset($info); } @@ -86,45 +87,10 @@ class gitea /* Sort by kind */ foreach($infos as $key => $info) $kinds[$key] = $info->kind; if($infos) array_multisort($kinds, SORT_ASC, $infos); + return $infos; } - /** - * Get files info. - * - * The API path requested is: "GET /projects/:id/repository/files/:file_path". - * Known issue of GitLab API: if a '%' in 'file_path', GitLab API will show a error 'file_path should be a valid file path'. - * - * @param string $path - * @param string $ref - * @access public - * @return object - * @doc https://docs.gitea.com/ee/api/repository_files.html - */ - public function files($path, $ref = 'master') - { - $path = urlencode($path); - $api = "contents/$path"; - $file = $this->fetch($api, array('ref' => $ref)); - if(!isset($file->name)) return false; - - $commits = $this->getCommitsByPath($path, '', '', 1, 1); - $file->revision = $file->sha; - $file->size = $this->formatBytes($file->size); - - if(!empty($commits)) - { - $commit = $commits[0]; - - $file->revision = $commit->sha; - $file->committer = $commit->commit->author->name; - $file->comment = $commit->commit->message; - $file->date = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); - } - - return $file; - } - /** * Get tags * @@ -135,69 +101,56 @@ class gitea */ public function tags($path, $revision = 'HEAD') { - $api = "tags"; - $tags = array(); + if(!scm::checkRevision($revision)) return array(); - $params = array(); - $params['limit'] = $this->pageLimit; - for($page = 1; true; $page ++) + chdir($this->root); + $cmd = escapeCmd("$this->client tag --sort=taggerdate"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); + + foreach($list as $key => $tag) { - $params['page'] = $page; - $list = $this->fetch($api, $params); - if(empty($list) or $list == '[]') break; - - foreach($list as $tag) $tags[] = $tag->name; - if(count($list) < $params['limit']) break; + if(!$tag) unset($list[$key]); } - return $tags; + return $list; } /** - * Get branches. + * Get branch. * * @access public * @return array */ public function branch() { - /* Max size of limit in gitea API is 50. */ - $params = array(); - $params['limit'] = $this->pageLimit; + chdir($this->root); + + /* Get local branch. */ + $cmd = escapeCmd("$this->client branch -a"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); /* Get default branch. */ - $project = $this->fetch(''); - $defaultBranch = $project->default_branch; + $defaultBranch = execCmd("$this->client symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'"); + $defaultBranch = trim($defaultBranch); $branches = array(); - $default = array(); - for($page = 1; true; $page ++) + foreach($list as $localBranch) { - $params['page'] = $page; - $branchList = $this->fetch("branches", $params); - if(empty($branchList)) break; + $localBranch = trim($localBranch); + if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue; + if(substr($localBranch, 0, 1) == '*') $localBranch = substr($localBranch, 1); + if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15); - foreach($branchList as $branch) - { - if(!isset($branch->name)) continue; - if($branch->name == $defaultBranch) - { - $default[$branch->name] = $branch->name; - } - else - { - $branches[$branch->name] = $branch->name; - } - } - - /* Last page. */ - if(count($branchList) < $params['limit']) break; + $localBranch = trim($localBranch); + if(empty($localBranch))continue; + if($localBranch != $defaultBranch) $branches[$localBranch] = $localBranch; } - if(empty($branches) and empty($default)) $branches['master'] = 'master'; asort($branches); + if($defaultBranch) $branches = array($defaultBranch => $defaultBranch) + $branches; - $branches = $default + $branches; return $branches; } @@ -211,11 +164,18 @@ class gitea */ public function getLastLog($path, $count = 10) { - return $this->log($path); + $path = ltrim($path, DIRECTORY_SEPARATOR); + $revision = $this->branch ? $this->branch : 'HEAD'; + + chdir($this->root); + $list = execCmd(escapeCmd("$this->client log -10 $revision -- $path"), 'array'); + $logs = $this->parseLog($list); + + return $logs; } /** - * Get logs. + * Get logs * * @param string $path * @param string $fromRevision @@ -231,13 +191,32 @@ class gitea $path = ltrim($path, DIRECTORY_SEPARATOR); $count = $count == 0 ? '' : "-n $count"; - $list = $this->getCommitsByPath($path, $fromRevision, $toRevision, 1, 1); - foreach($list as $commit) + /* compatible with svn. */ + if($fromRevision == 'HEAD' and $this->branch) $fromRevision = $this->branch; + if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch; + if($fromRevision === $toRevision) { - if(isset($commit->sha)) $commit->diffs = $this->getFilesByCommit($commit->sha); + $logs = array(); + chdir($this->root); + + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 -1 $fromRevision -- $path"), 'array'); + $logs = $this->parseLog($list); + return $logs; } - return $this->parseLog($list); + if(!$fromRevision) + { + $revisions = " $toRevision"; + } + else + { + $revisions = "$fromRevision..$toRevision"; + } + chdir($this->root); + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 $count $revisions -- $path"), 'array'); + $logs = $this->parseLog($list); + + return $logs; } /** @@ -250,7 +229,46 @@ class gitea */ public function blame($path, $revision) { - return array(); + if(!scm::checkRevision($revision)) return array(); + + $path = ltrim($path, DIRECTORY_SEPARATOR); + chdir($this->root); + $list = execCmd(escapeCmd("$this->client blame -l $revision -- $path"), 'array'); + + $blames = array(); + $revLine = 0; + $revision = ''; + foreach($list as $line) + { + if(empty($line)) continue; + if($line[0] == '^') $line = substr($line, 1); + preg_match('/^([0-9a-f]{39,40})\s.*\((\S+)\s+([\d-]+)\s(.*)\s(\d+)\)(.*)$/U', $line, $matches); + + if(isset($matches[1]) and $matches[1] != $revision) + { + $blame = array(); + $blame['revision'] = $matches[1]; + $blame['committer'] = $matches[2]; + $blame['time'] = $matches[3]; + $blame['line'] = $matches[5]; + $blame['lines'] = 1; + $blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1); + + $revision = $matches[1]; + $revLine = $matches[5]; + $blames[$revLine] = $blame; + } + elseif(isset($matches[5])) + { + $blame = array(); + $blame['line'] = $matches[5]; + $blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1); + + $blames[$matches[5]] = $blame; + $blames[$revLine]['lines'] ++; + } + } + return $blames; } /** @@ -259,19 +277,25 @@ class gitea * @param string $path * @param string $fromRevision * @param string $toRevision - * @param string $fromProject * @param string $extra * @access public * @return array */ - public function diff($path, $fromRevision, $toRevision, $fromProject = '', $extra = '') + public function diff($path, $fromRevision, $toRevision, $extra = '') { if(!scm::checkRevision($fromRevision) and $extra != 'isBranchOrTag') return array(); if(!scm::checkRevision($toRevision) and $extra != 'isBranchOrTag') return array(); - $diffApi = "{$this->root}git/commits/$toRevision.diff?token={$this->token}"; - $diffs = commonModel::http($diffApi); - $lines = explode("\n", $diffs); + $path = ltrim($path, DIRECTORY_SEPARATOR); + chdir($this->root); + if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch; + if($fromRevision == '^') $fromRevision = $toRevision . '^'; + if(strpos($fromRevision, '^') !== false) + { + $list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array'); + if(isset($list[1])) $fromRevision = $list[1]; + } + $lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array'); return $lines; } @@ -286,9 +310,13 @@ class gitea public function cat($entry, $revision = 'HEAD') { if(!scm::checkRevision($revision)) return false; + + chdir($this->root); if($revision == 'HEAD' and $this->branch) $revision = $this->branch; - $file = $this->files($entry, $revision); - return base64_decode($file->content); + $cmd = escapeCmd("$this->client show $revision:$entry"); + $content = execCmd($cmd); + if(is_array($content)) $content = implode("\n", $content); + return $content; } /** @@ -303,28 +331,33 @@ class gitea { if(!scm::checkRevision($revision)) return false; - $info = new stdclass(); - $info->kind = 'dir'; - $info->path = $entry; - $info->revision = $revision; - $info->root = ''; - if($revision == 'HEAD' and $this->branch) $info->revision = $this->branch; - - if($entry) + chdir($this->root); + if($revision == 'HEAD' and $this->branch) $revision = $this->branch; + $path = ltrim($entry, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client ls-tree $revision -- $path"); + $result = execCmd($cmd); + $kind = ''; + if($result) { - $parent = dirname($entry); - if($parent == '.') $parent = '/'; - if($parent == '') $parent = '/'; - $list = $this->tree($parent, 0); - $file = new stdclass(); - - foreach($list as $node) if($node->path == $entry) $file = $node; - - $commits = $this->getCommitsByPath($entry, $revision, $revision); - if(!empty($commits)) $file->revision = zget($commits[0], 'sha', ''); - $info->kind = (isset($file->type) and $file->type == 'tree') ? 'dir' : 'file'; + $results = explode("\n", trim($result)); + if(count($results) >= 2) + { + $kind = 'dir'; + } + else + { + list($mode, $type) = explode(' ', $results[0]); + $kind = $type == 'tree' ? 'dir' : 'file'; + } } + $list = execCmd(escapeCmd("$this->client log -1 $revision --pretty=format:%H -- $path"), 'array'); + $revision = $list[0]; + $info = new stdclass(); + $info->kind = $kind; + $info->path = $entry; + $info->revision = $revision; + $info->root = $this->root; return $info; } @@ -333,11 +366,11 @@ class gitea * * @param string $cmd * @access public - * @todo Exec commands by gitea api. * @return array */ public function exec($cmd) { + chdir($this->root); return execCmd(escapeCmd("$this->client $cmd"), 'array'); } @@ -489,280 +522,90 @@ class gitea /** * Get commits. * - * @param string $version + * @param string $rversion * @param int $count * @param string $branch * @access public * @return array */ - public function getCommits($version = '', $count = 0, $branch = '') + public function getCommits($revision = '', $count = 0, $branch = '') { - if(!scm::checkRevision($version)) return array(); - $api = "commits"; - $commits = array(); - $files = array(); + if(!scm::checkRevision($revision)) return array(); - if(empty($count)) $count = $this->pageLimit; + if($revision == 'HEAD' and $branch) $revision = $branch; + $revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision; + $count = $count == 0 ? '' : "-n $count"; - if(!empty($version) and $count == 1) + chdir($this->root); + if($branch) { - $commits = $this->fetch($api, array('limit' => 1, 'sha' => $version)); - $commit = $commits[0]; - if(isset($commit->sha)) - { - $log = new stdclass; - $log->committer = $commit->commit->author->name; - $log->revision = $commit->sha; - $log->comment = $commit->commit->message; - $log->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); - - $commits[$commit->sha] = $log; - $files[$commit->sha] = $this->getFilesByCommit($log->revision); - - return array('commits' => $commits, 'files' => $files); - } + execCmd(escapeCmd("$this->client checkout $branch")); + execCmd(escapeCmd("$this->client pull")); } - $params['sha'] = $branch; - if($version and $version != 'HEAD') + $list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array'); + $commits = $this->parseLog($list); + + $logs = array(); + foreach($commits as $commit) { - /* Get since param. */ - if(substr($version, 0, 5) == 'since') - { - $since = true; - $version = substr($version, 5); - } + $hash = $commit->revision; + $log = new stdClass(); + $log->committer = $commit->committer; + $log->revision = $commit->revision; + $log->comment = $commit->comment; + $log->time = $commit->time; + $logs['commits'][$hash] = $log; + $logs['files'][$hash] = array(); + } + if(empty($logs)) return $logs; - $committedDate = $this->getCommittedDate($version); - if(!$committedDate) return array('commits' => array(), 'files' => array()); - - if(!empty($since)) + $hash = ''; + $files = execCmd(escapeCmd("$this->client whatchanged $count $revision --pretty=format:%an@_@%cd@_@%H@_@%s -- ./"), 'array'); + foreach($files as $commit) + { + $commit = trim($commit); + if(empty($commit)) continue; + $parsedCommit = explode('@_@', $commit); + if(count($parsedCommit) == 4) { - $params['since'] = $committedDate; + list($account, $date, $hash, $comment) = $parsedCommit; } else { - $params['until'] = $committedDate; + $file = explode(' ', $commit); + $file = explode("\t", end($file)); + if(!isset($file[1])) $file[1] = ''; + list($action, $path) = $file; + + $parsedFile = new stdclass(); + $parsedFile->revision = $hash; + $parsedFile->path = '/' . trim($path); + $parsedFile->type = 'file'; + $parsedFile->action = $action; + $logs['files'][$hash][] = $parsedFile; } } - - $list = $this->fetch($api, $params); - - foreach($list as $commit) - { - if(!isset($commit->commit) or !is_object($commit->commit)) continue; - - $log = new stdclass; - $log->committer = $commit->commit->author->name; - $log->revision = $commit->sha; - $log->comment = $commit->commit->message; - $log->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); - - $commits[$commit->sha] = $log; - $files[$commit->sha] = $this->getFilesByCommit($log->revision); - } - - return array('commits' => $commits, 'files' => $files); + return $logs; } /** - * getCommit + * Get clone url. * - * @param int $sha - * @access public - * @return void - */ - public function getCommittedDate($sha) - { - if(!scm::checkRevision($sha)) return null; - if(!$sha or $sha == 'HEAD') return date('c'); - - global $dao; - $time = $dao->select('time')->from(TABLE_REPOHISTORY)->where('revision')->eq($sha)->fetch('time'); - if($time) return date('c', strtotime($time)); - - $params = array(); - $params['sha'] = $sha; - $params['limit'] = 1; - $result = $this->fetch("commits", $params); - return (isset($resulti[0]->created)) ? date('Y-m-d H:i:s', strtotime($result->created)) : false; - } - - /** - * Get commits by path. - * - * @param string $path - * @param string $fromRevision - * @param string $toRevision - * @param int $perPage - * @access public - * @return array - */ - public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0, $limit = 0) - { - $path = ltrim($path, DIRECTORY_SEPARATOR); - $api = "commits"; - - if(!$limit) $limit = $this->pageLimit; - $param = new stdclass(); - $param->path = urldecode($path); - $param->limit = $limit; - $param->sha = ($toRevision != 'HEAD' and $toRevision) ? $toRevision : $this->branch; - - if($perPage) $param->page = $perPage; - return $this->fetch($api, $param); - } - - /** - * Get diff files by reviesion. - * - * @param int $reviesion - * @access public - * @return array - */ - public function getDiffFiles($revision) - { - $diffApi = "{$this->root}git/commits/$revision.patch?token={$this->token}"; - $diffs = commonModel::http($diffApi); - - $newFiles = array(); - $delFiles = array(); - - if(!empty($diffs)) - { - $diffs = explode("\n", $diffs); - foreach($diffs as $row) - { - preg_match('/^(\s)(create|delete)\smode\s\d+\s(.+)$/', $row, $matches); - if(count($matches) == 4 and !in_array($matches[3], $newFiles) and !in_array($matches[3], $delFiles)) - { - if($matches[2] == 'create') - { - $newFiles[] = $matches[3]; - } - elseif($matches[2] == 'delete') - { - $delFiles[] = $matches[3]; - } - } - } - } - - return array('newFiles' => $newFiles, 'delFiles' => $delFiles); - } - - /** - * Get files by commit. - * - * @param string $commit - * @access public - * @return void - */ - public function getFilesByCommit($revision) - { - if(!scm::checkRevision($revision)) return array(); - $api = "git/commits/$revision"; - $results = $this->fetch($api); - if(empty($results)) return array(); - - $diffFiles = $this->getDiffFiles($revision); - $files = array(); - foreach($results->files as $row) - { - $file = new stdclass(); - $file->revision = $revision; - $file->type = 'file'; - $file->path = '/' . $row->filename; - $file->action = 'M'; - if(in_array($row->filename, $diffFiles['newFiles'])) - { - $file->action = 'A'; - } - elseif(in_array($row->filename, $diffFiles['delFiles'])) - { - $file->action = 'D'; - } - - $files[] = $file; - } - - return $files; - } - - /** - * Repository/tree api. - * - * @param string $path - * @param bool $recursive - * @access public - * @return mixed - */ - public function tree($path, $recursive = 1) - { - $api = "contents"; - - $params = array(); - $params['path'] = ltrim($path, '/'); - $params['ref'] = $this->branch; - $params['recursive'] = (int) $recursive; - return $this->fetch($api, $params); - } - - /** - * Fetch data from gitea api. - * - * @param string $api - * @access public - * @return mixed - */ - public function fetch($api, $params = array(), $needToLoop = false) - { - $params = (array) $params; - $params['token'] = $this->token; - $params['limit'] = isset($params['limit']) ? $params['limit'] : $this->pageLimit; - - $api = ltrim($api, '/'); - $api = $this->root . $api . '?' . http_build_query($params); - if($needToLoop) - { - $allResults = array(); - for($page = 1; true; $page++) - { - $results = json_decode(commonModel::http($api . "&page={$page}")); - if(!is_array($results)) break; - if(!empty($results)) $allResults = array_merge($allResults, $results); - if(count($results) < $this->pageLimit) break; - } - - return $allResults; - } - else - { - $response = commonModel::http($api); - if(!empty(commonModel::$requestErrors)) - { - commonModel::$requestErrors = array(); - return array(); - } - - return json_decode($response); - } - } - - /** - * Format bytes shown. - * - * @param int $size - * @static * @access public * @return string */ - public static function formatBytes($size) + public function getCloneUrl() { - if($size < 1024) return $size . 'Bytes'; - if(round($size / (1024 * 1024), 2) > 1) return round($size / (1024 * 1024), 2) . 'G'; - if(round($size / 1024, 2) > 1) return round($size / 1024, 2) . 'M'; - return round($size, 2) . 'KB'; + $url = new stdclass(); + $remote = execCmd(escapeCmd("$this->client remote -v"), 'array'); + $pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + $pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + + if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0]; + if(preg_match($pregSSH, $remote[0], $matches)) $url->ssh = $matches[0]; + + return $url; } /** @@ -776,39 +619,56 @@ class gitea { $parsedLogs = array(); $i = 0; - foreach($logs as $commit) + foreach($logs as $line) { - if(!isset($commit->sha)) continue; - $parsedLog = new stdclass(); - $parsedLog->revision = $commit->sha; - $parsedLog->committer = $commit->commit->author->name; - $parsedLog->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); - $parsedLog->comment = $commit->commit->message; - $parsedLog->change = array(); - foreach($commit->diffs as $diff) + if(strpos($line, 'commit ') === 0) { - $parsedLog->change[$diff->path] = array(); - $parsedLog->change[$diff->path]['action'] = $diff->action; - $parsedLog->change[$diff->path]['kind'] = $diff->type; + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; + $i++; + } + + $log = new stdclass(); + $comment = ''; + $changes = array(); + + $log->revision = trim(preg_replace('/^commit/', '', $line)); } - $parsedLogs[] = $parsedLog; + elseif(strpos($line, 'Author:') === 0) + { + $account = preg_replace('/^Author:/', '', $line); + $log->committer = trim(preg_replace('/<[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+>/', '', $account)); + } + elseif(strpos($line, 'Date:') === 0) + { + $date = trim(preg_replace('/^Date:/', '', $line)); + $log->time = date('Y-m-d H:i:s', strtotime($date)); + } + elseif(preg_match('/^\s{2,}/', $line)) + { + $comment .= $line; + } + elseif(strpos($line, "\t") !== false) + { + list($action, $entry) = explode("\t", $line); + $entry = '/' . trim($entry); + $pathInfo = array(); + $pathInfo['action'] = $action; + $pathInfo['kind'] = 'file'; + $changes[$entry] = $pathInfo; + } + } + + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; } return $parsedLogs; } - - /** - * Get download url. - * - * @param string $branch - * @param string $ext - * @access public - * @return string - */ - public function getDownloadUrl($branch = 'master', $ext = 'zip') - { - $params['token'] = $this->token; - - return "{$this->root}archive/" . urlencode($branch) . ".{$ext}" . '?' . http_build_query($params); - } } diff --git a/lib/scm/gitrepo.class.php b/lib/scm/gitrepo.class.php index 92729062cb..1e947489ad 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -21,7 +21,7 @@ class GitRepo $this->client = $client; $this->root = rtrim($root, DIRECTORY_SEPARATOR); - $this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : ''; + $this->branch = isset($_COOKIE['repoBranch']) ? 'origin/' . $_COOKIE['repoBranch'] : ''; chdir($this->root); exec("{$this->client} config core.quotepath false"); @@ -117,7 +117,7 @@ class GitRepo } /** - * Get branch + * Get branch. * * @access public * @return array @@ -127,17 +127,21 @@ class GitRepo chdir($this->root); /* Get local branch. */ - $cmd = escapeCmd("$this->client branch"); + $cmd = escapeCmd("$this->client branch -a"); $list = execCmd($cmd . ' 2>&1', 'array', $result); if($result) return array(); /* Get default branch. */ $defaultBranch = execCmd("$this->client symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'"); + $defaultBranch = trim($defaultBranch); $branches = array(); foreach($list as $localBranch) { + $localBranch = trim($localBranch); + if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue; if(substr($localBranch, 0, 1) == '*') $localBranch = substr($localBranch, 1); + if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15); $localBranch = trim($localBranch); if(empty($localBranch))continue; @@ -533,6 +537,8 @@ class GitRepo $count = $count == 0 ? '' : "-n $count"; chdir($this->root); + if($branch) execCmd(escapeCmd("$this->client checkout $branch"), 'array'); + $list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array'); $commits = $this->parseLog($list); diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 38218a2bd1..dd04ece590 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, imported by $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testcase->common . ' by $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 51cedddc58..1a927d1e7e 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, imported by $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testcase->common . ' by $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index f50eae6e17..534a5cbe99 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, Importé par $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, MàJ de ' . $lang->testcase->common . ' par $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor a créé un sous-tâche $extra。' . "\n"; diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index 56a4ac1674..09f6928001 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -176,6 +176,8 @@ $lang->action->desc->run = '$date, by $actor execut $lang->action->desc->syncprogram = '$date, started by $actor(starting the project sets the program status as Ongoing).' . "\n"; $lang->action->desc->syncproject = '$date, starting the execution sets the project status as Ongoing.' . "\n"; $lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index eda00b9ed1..f3a4d1a7cc 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, 由 $actor $lang->action->desc->tolib = '$date, 由 $actor 导入。' . "\n"; $lang->action->desc->updatetolib = '$date, 由 $actor 从' . $lang->testcase->common . '更新。' . "\n"; $lang->action->desc->adjusttasktowait = '$date, 系统判断由于消耗工时调整为0,将任务状态置为未开始。' . "\n"; +$lang->action->desc->reopen = '$date, 由 $actor 重新打开。' . "\n"; +$lang->action->desc->merged = '$date, 由 $actor 合并。' . "\n"; /* 用来描述和父子任务相关的操作历史记录。*/ $lang->action->desc->createchildren = '$date, 由 $actor 创建子任务 $extra。' . "\n"; diff --git a/module/gitea/model.php b/module/gitea/model.php index 1b52f42608..5ee5469e49 100644 --- a/module/gitea/model.php +++ b/module/gitea/model.php @@ -600,4 +600,36 @@ class giteaModel extends model return $newBranches; } + + /** + * Check remote url. + * + * @param int $giteaID + * @param string $project + * @param string $client + * @param string $path + * @access public + * @return bool + */ + public function checkRemoteUrl($giteaID, $project, $client, $path) + { + if(chdir($path)) + { + $url = new stdclass(); + $remote = execCmd(escapeCmd("$client remote -v"), 'array'); + $pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + $pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + + if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0]; + if(preg_match($pregSSH, $remote[0], $matches)) $url->ssh = $matches[0]; + + $project = $this->apiGetSingleProject($giteaID, $project); + if(isset($project->clone_url)) + { + if($project->clone_url == $url->http or $project->ssh_url == $url->ssh) return true; + } + } + + return false; + } } diff --git a/module/mr/control.php b/module/mr/control.php index 7fe28b3372..85e6294589 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -976,7 +976,7 @@ class mr extends control public function ajaxGetRepoList($hostID, $projectID) { $host = $this->loadModel('pipeline')->getByID($hostID); - if($host->type != 'gitlab') $projectID =urldecode(base64_decode($projectID)); + if($host->type != 'gitlab') $projectID = urldecode(base64_decode($projectID)); $repoList = $this->loadModel('repo')->getRepoListByClient($hostID, $projectID); diff --git a/module/mr/css/browse.css b/module/mr/css/browse.css index 37c751af56..2178adff41 100644 --- a/module/mr/css/browse.css +++ b/module/mr/css/browse.css @@ -15,6 +15,6 @@ .c-id {width: 60px;} .c-title {min-width: 120px;} .c-branch {width: 240px;} -.c-status {width: 100px;} +.c-status {width: 120px;} .c-author {width: 100px;} .c-date {width: 140px;} diff --git a/module/mr/model.php b/module/mr/model.php index 66d7129e2c..e85a33f5a6 100644 --- a/module/mr/model.php +++ b/module/mr/model.php @@ -400,6 +400,8 @@ class mrModel extends model $MR = $this->getByID($MRID); $this->linkObjects($MR); + $this->loadModel('action')->create('mr', $MRID, 'edited'); + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'browse')); } @@ -1018,13 +1020,9 @@ class mrModel extends model $host = $this->loadModel('pipeline')->getByID($MR->hostID); $scm = $host->type; - $this->loadModel('repo'); - $repo = new stdclass; - $repo->SCM = $this->lang->repo->scmList[ucfirst($scm)]; + $repo = $this->loadModel('repo')->getRepoByID($MR->repoID); $repo->gitService = $host->id; $repo->project = $MR->targetProject; - $repo->path = sprintf($this->config->repo->$scm->apiPath, $host->url, $MR->targetProject); - $repo->client = $host->url; $repo->password = $host->token; $repo->account = ''; $repo->encoding = $encoding; @@ -1865,7 +1863,7 @@ class mrModel extends model */ public function logMergedAction($MR) { - $this->loadModel('action'); + $this->loadModel('action')->create('mr', $MR->id, 'merged'); $product = $this->getMRProduct($MR); $stories = $this->getLinkList($MR->id, $product->id, 'story'); diff --git a/module/repo/js/create.js b/module/repo/js/create.js index d6db74f6e3..1c2d0a00f2 100644 --- a/module/repo/js/create.js +++ b/module/repo/js/create.js @@ -54,7 +54,7 @@ $(function() */ function scmChanged(scm) { - if(scm == 'Git') + if(scm == 'Git' || scm == 'Gitea') { $('.account-fields').addClass('hidden'); @@ -77,7 +77,14 @@ function scmChanged(scm) else { $('tr.service').toggle(true); - $('tr.hide-service').toggle(false); + if(scm == 'Gitea') + { + $('tr.hide-service').toggle(true); + } + else + { + $('tr.hide-service').toggle(false); + } var url = createLink('repo', 'ajaxGetHosts', "scm=" + scm); $.get(url, function(response) diff --git a/module/repo/js/edit.js b/module/repo/js/edit.js index 229f4907ab..6f8167d17c 100644 --- a/module/repo/js/edit.js +++ b/module/repo/js/edit.js @@ -38,7 +38,7 @@ $(function() */ function scmChanged(scm, isFirstRequest = false) { - if(scm == 'Git') + if(scm == 'Git' || scm == 'Gitea') { $('.account-fields').addClass('hidden'); @@ -61,7 +61,14 @@ function scmChanged(scm, isFirstRequest = false) else { $('tr.service').toggle(true); - $('tr.hide-service').toggle(false); + if(scm == 'Gitea') + { + $('tr.hide-service').toggle(true); + } + else + { + $('tr.hide-service').toggle(false); + } if(!isFirstRequest) { diff --git a/module/repo/lang/de.php b/module/repo/lang/de.php index cffe5ebcfd..4f5484b589 100644 --- a/module/repo/lang/de.php +++ b/module/repo/lang/de.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'You may find the reference about how to set Git sync from here.'; $lang->repo->encodingsTips = "The encodings of comments can be comma separated values, e.g. utf-8."; diff --git a/module/repo/lang/en.php b/module/repo/lang/en.php index 725f3d2263..a29be6e3c7 100644 --- a/module/repo/lang/en.php +++ b/module/repo/lang/en.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'You may find the reference about how to set Git sync from here.'; $lang->repo->encodingsTips = "The encodings of comments can be comma separated values, e.g. utf-8."; diff --git a/module/repo/lang/fr.php b/module/repo/lang/fr.php index 22661b03db..5e77a34092 100644 --- a/module/repo/lang/fr.php +++ b/module/repo/lang/fr.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'Vous pouvez trouver la référence sur la façon de définir la synchronisation Git à partir de la page se trouvant ici.'; $lang->repo->encodingsTips = "Les encodages des commentaires de validation peuvent être des valeurs séparées par des virgules,ex: utf-8"; diff --git a/module/repo/lang/vi.php b/module/repo/lang/vi.php index e84f6866e6..a6ce017675 100644 --- a/module/repo/lang/vi.php +++ b/module/repo/lang/vi.php @@ -189,6 +189,7 @@ $lang->repo->error->encoding = "The encoding maybe wrong. Vui lòng change $lang->repo->error->deleted = "Deletion of the repository failed. The current repository has a commit record associated with the design."; $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'Bạn có thể tìm tham khảo làm sao thiết lập đồng bộ Git từ here.'; $lang->repo->encodingsTips = "The encodings of commit comments, can be comma separated values,ví dụ: utf-8"; diff --git a/module/repo/lang/zh-cn.php b/module/repo/lang/zh-cn.php index d9c12cd196..d3fa3981e7 100644 --- a/module/repo/lang/zh-cn.php +++ b/module/repo/lang/zh-cn.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "删除代码库失败,当前代码库与 $lang->repo->error->clientPath = "客户端安装目录不能有空格!"; $lang->repo->error->notFound = "代码库『%s』路径 %s 不存在,请确认此代码库是否已在本地服务器被删除"; $lang->repo->error->noWritable = '%s 不可写!请检查该目录权限,否则无法下载。'; +$lang->repo->error->unconnected = '目录地址与仓库不匹配'; $lang->repo->syncTips = '请参照这里,设置代码库定时同步。'; $lang->repo->encodingsTips = "提交日志的编码,可以用逗号连接起来的多个,比如utf-8。"; diff --git a/module/repo/model.php b/module/repo/model.php index c5ff290a53..c0266a4bb2 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -122,7 +122,8 @@ class repoModel extends model $productIdList = $this->loadModel('product')->getProductIDByProject($projectID, false); foreach($repos as $i => $repo) { - $repo->acl = json_decode($repo->acl); + $repo->acl = json_decode($repo->acl); + $repo->codePath = $repo->path; if(!$this->checkPriv($repo)) { unset($repos[$i]); @@ -166,7 +167,8 @@ class repoModel extends model foreach($repos as $i => $repo) { if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); - $repo->acl = json_decode($repo->acl); + $repo->acl = json_decode($repo->acl); + $repo->codePath = $repo->path; if($type == 'haspriv' and !$this->checkPriv($repo)) unset($repos[$i]); if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); } @@ -195,8 +197,8 @@ class repoModel extends model $data = fixer::input('post') ->setIf($isPipelineServer, 'password', $this->post->serviceToken) - ->setIf($isPipelineServer, 'path', $this->post->serviceProject) - ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '') + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '') ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) ->setIf($isPipelineServer, 'prefix', '') ->setIf($this->post->SCM == 'Git', 'account', '') @@ -206,12 +208,12 @@ class repoModel extends model ->join('product', ',') ->get(); - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) + if($isPipelineServer) { $repo = $this->dao->select('id')->from(TABLE_REPO) ->where('SCM')->eq($this->post->SCM) - ->andWhere('client')->eq($data->client) - ->andWhere('path')->eq($data->path) + ->andWhere('serviceHost')->eq($data->client) + ->andWhere('serviceProject')->eq($data->path) ->fetch(); if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name); if(dao::isError()) return false; @@ -219,6 +221,15 @@ class repoModel extends model $data->acl = empty($data->acl) ? '' : json_encode($data->acl); + if($data->SCM == 'Gitea') + { + $relation = $this->loadModel('gitea')->checkRemoteUrl($data->serviceHost, $data->serviceProject, $data->client, $data->path); + if(!$relation) + { + dao::$errors['path'] = $this->lang->repo->error->unconnected; + return false; + } + } if($data->SCM == 'Subversion') { $scm = $this->app->loadClass('scm'); @@ -230,10 +241,11 @@ class repoModel extends model } if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceHost,serviceToken,serviceProject') + $this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceToken') ->batchCheck($this->config->repo->create->requiredFields, 'notempty') - ->checkIF($isPipelineServer, 'serviceProject', 'notempty') + ->checkIF($isPipelineServer, 'serviceHost,serviceProject', 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') + ->checkIF($data->SCM == 'Gitea', $this->config->repo->gitea->requiredFields, 'notempty') ->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git'") ->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion'") ->autoCheck() @@ -275,8 +287,8 @@ class repoModel extends model $data = fixer::input('post') ->setIf($isPipelineServer, 'password', $this->post->serviceToken) - ->setIf($isPipelineServer, 'path', $this->post->serviceProject) - ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '') + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '') ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) ->setDefault('prefix', $repo->prefix) ->setIf($this->post->SCM == 'Gitlab', 'prefix', '') @@ -304,12 +316,12 @@ class repoModel extends model $data->prefix = ''; } - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) + if($isPipelineServer) { $repo = $this->dao->select('id')->from(TABLE_REPO) ->where('SCM')->eq($this->post->SCM) - ->andWhere('client')->eq($data->client) - ->andWhere('path')->eq($data->path) + ->andWhere('serviceHost')->eq($data->client) + ->andWhere('serviceProject')->eq($data->path) ->andWhere('id')->ne($id) ->fetch(); if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name); @@ -320,7 +332,7 @@ class repoModel extends model if(!$this->checkConnection()) return false; if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->update(TABLE_REPO)->data($data, $skip = 'serviceHost,serviceToken,serviceProject') + $this->dao->update(TABLE_REPO)->data($data, $skip = 'serviceToken') ->batchCheck($this->config->repo->edit->requiredFields, 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') ->checkIF($data->SCM == 'Gitlab', 'extra', 'notempty') @@ -463,6 +475,7 @@ class repoModel extends model if(!$repo) return false; if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); + $repo->codePath = $repo->path; if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); $repo->acl = json_decode($repo->acl); return $repo; @@ -1285,7 +1298,7 @@ class repoModel extends model */ public function checkClient() { - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) return true; + if($this->post->SCM == 'Gitlab') return true; if(!$this->config->features->checkClient) return true; if(!$this->post->client) @@ -1409,7 +1422,7 @@ class repoModel extends model return false; } } - elseif($scm == 'Git') + elseif(in_array($scm, array('Git', 'Gitea'))) { if(!is_dir($path)) { @@ -2035,13 +2048,22 @@ class repoModel extends model */ public function processGitService($repo) { - $service = $this->loadModel('pipeline')->getByID($repo->client); + $service = $this->loadModel('pipeline')->getByID($repo->serviceHost); + if($repo->SCM == 'Gitlab') + { + $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject); - $repo->gitService = $service ? $service->id : 0; - $repo->project = $service ? $repo->path : ''; // The projectID in gitlab. - $repo->path = $service ? sprintf($this->config->repo->{$service->type}->apiPath, $service->url, $repo->path) : ''; - $repo->client = $service ? $service->url : ''; - $repo->password = $service ? $service->token : ''; + $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; + } + elseif($repo->SCM == 'Gitea') + { + $repo->codePath = $service ? "{$service->url}/{$repo->serviceProject}" : $repo->path; + } + $repo->gitService = $repo->serviceHost; + $repo->project = $repo->serviceProject; return $repo; } @@ -2056,8 +2078,8 @@ class repoModel extends model { return $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0') ->andWhere('synced')->eq(1) - ->andWhere('client')->eq($gitlabID) - ->beginIF($projectID)->andWhere('path')->eq($projectID)->fi() + ->andWhere('serviceHost')->eq($gitlabID) + ->beginIF($projectID)->andWhere('serviceProject')->eq($projectID)->fi() ->fetchAll(); } diff --git a/module/repo/view/ajaxsidecommits.html.php b/module/repo/view/ajaxsidecommits.html.php index a78b02425a..27102e03ee 100644 --- a/module/repo/view/ajaxsidecommits.html.php +++ b/module/repo/view/ajaxsidecommits.html.php @@ -19,9 +19,7 @@ if(isset($entry)) $pathInfo .= '&type=file'; - SCM != 'Gitea'):?> - SCM != 'Subversion'):?> @@ -34,14 +32,12 @@ if(isset($entry)) $pathInfo .= '&type=file'; - SCM != 'Gitea'):?> - SCM != 'Subversion'):?> @@ -54,7 +50,7 @@ if(isset($entry)) $pathInfo .= '&type=file';
repo->revisionA?> repo->commit?>
repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$log->revision}" . $pathInfo), $repo->SCM != 'Subversion' ? substr($log->revision, 0, 10) : $log->revision, '', "data-app='{$this->app->tab}'");?> commit?>