From f94aff639d47c440a8c04a21caa6d834b7217407 Mon Sep 17 00:00:00 2001 From: liyuchun <563917701@qq.com> Date: Mon, 1 Aug 2022 02:48:23 +0000 Subject: [PATCH 001/106] * Add gogs module. --- module/gogs/config.php | 6 + module/gogs/control.php | 222 +++++++++++ module/gogs/css/browse.css | 2 + module/gogs/css/common.css | 2 + module/gogs/lang/de.php | 36 ++ module/gogs/lang/en.php | 36 ++ module/gogs/lang/fr.php | 36 ++ module/gogs/lang/vi.php | 36 ++ module/gogs/lang/zh-cn.php | 36 ++ module/gogs/lang/zh-tw.php | 33 ++ module/gogs/model.php | 607 +++++++++++++++++++++++++++++ module/gogs/view/binduser.html.php | 85 ++++ module/gogs/view/browse.html.php | 73 ++++ module/gogs/view/create.html.php | 45 +++ module/gogs/view/edit.html.php | 45 +++ module/gogs/view/view.html.php | 37 ++ 16 files changed, 1337 insertions(+) create mode 100644 module/gogs/config.php create mode 100644 module/gogs/control.php create mode 100644 module/gogs/css/browse.css create mode 100644 module/gogs/css/common.css create mode 100644 module/gogs/lang/de.php create mode 100644 module/gogs/lang/en.php create mode 100644 module/gogs/lang/fr.php create mode 100644 module/gogs/lang/vi.php create mode 100644 module/gogs/lang/zh-cn.php create mode 100644 module/gogs/lang/zh-tw.php create mode 100644 module/gogs/model.php create mode 100644 module/gogs/view/binduser.html.php create mode 100644 module/gogs/view/browse.html.php create mode 100644 module/gogs/view/create.html.php create mode 100644 module/gogs/view/edit.html.php create mode 100644 module/gogs/view/view.html.php diff --git a/module/gogs/config.php b/module/gogs/config.php new file mode 100644 index 0000000000..88dddfa1f6 --- /dev/null +++ b/module/gogs/config.php @@ -0,0 +1,6 @@ +gogs->create = new stdclass; +$config->gogs->create->requiredFields = 'name,url,token'; + +$config->gogs->edit = new stdclass; +$config->gogs->edit->requiredFields = 'name,url,token'; diff --git a/module/gogs/control.php b/module/gogs/control.php new file mode 100644 index 0000000000..50121cd32a --- /dev/null +++ b/module/gogs/control.php @@ -0,0 +1,222 @@ + + * @package product + * @version $Id: ${FILE_NAME} 5144 2022-08-01 liyuchun@easycorp.ltd $ + * @link http://www.zentao.net + */ +class gogs extends control +{ + /** + * The gogs constructor. + * @param string $moduleName + * @param string $methodName + */ + public function __construct($moduleName = '', $methodName = '') + { + parent::__construct($moduleName, $methodName); + + /* This is essential when changing tab(menu) from gogs to repo. */ + /* Optional: common::setMenuVars('devops', $this->session->repoID); */ + $this->loadModel('ci')->setMenu(); + } + + /** + * Browse gogs. + * + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + /* Admin user don't need bind. */ + $gogsList = $this->gogs->getList($orderBy, $pager); + $myGogses = $this->gogs->getGogsListByAccount(); + foreach($gogsList as $gogs) + { + $gogs->isBindUser = true; + if(!$this->app->user->admin and !isset($myGogses[$gogs->id])) $gogs->isBindUser = false; + } + + $this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->browse; + $this->view->gogsList = $gogsList; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * Create a gogs. + * + * @access public + * @return void + */ + public function create() + { + if($_POST) + { + $this->checkToken(); + $gogsID = $this->gogs->create(); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + $actionID = $this->loadModel('action')->create('gogs', $gogsID, 'created'); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->lblCreate; + + $this->display(); + } + + /** + * View a gogs. + * @param int $gogsID + * @access public + * @return void + */ + public function view($gogsID) + { + $gogs = $this->gogs->getByID($gogsID); + + $this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->view; + $this->view->gogs = $gogs; + $this->view->users = $this->loadModel('user')->getPairs('noclosed'); + $this->view->actions = $this->loadModel('action')->getList('gogs', $gogsID); + $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('pipeline', $gogsID); + $this->display(); + } + + /** + * Edit a gogs. + * + * @param int $gogsID + * @access public + * @return void + */ + public function edit($gogsID) + { + $oldGogs = $this->gogs->getByID($gogsID); + + if($_POST) + { + $this->checkToken(); + $this->gogs->update($gogsID); + $gogs = $this->gogs->getByID($gogsID); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $this->loadModel('action'); + $actionID = $this->action->create('gogs', $gogsID, 'edited'); + $changes = common::createChanges($oldGogs, $gogs); + $this->action->logHistory($actionID, $changes); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->edit; + $this->view->gogs = $oldGogs; + + $this->display(); + } + + /** + * Delete a gogs. + * + * @param int $gogsID + * @access public + * @return void + */ + public function delete($gogsID, $confirm = 'no') + { + if($confirm != 'yes') return print(js::confirm($this->lang->gogs->confirmDelete, inlink('delete', "id=$gogsID&confirm=yes"))); + + + $oldGogs = $this->loadModel('pipeline')->getByID($gogsID); + $actionID = $this->pipeline->delete($gogsID, 'gogs'); + + $gogs = $this->pipeline->getByID($gogsID); + $changes = common::createChanges($oldGogs, $gogs); + $this->loadModel('action')->logHistory($actionID, $changes); + return print(js::reload('parent')); + } + + /** + * Check post token has admin permissions. + * + * @access protected + * @return void + */ + protected function checkToken() + { + $gogs = fixer::input('post')->trim('url,token')->get(); + $this->dao->update('gogs')->data($gogs)->batchCheck($this->config->gogs->create->requiredFields, 'notempty'); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $result = $this->gogs->checkTokenAccess($gogs->url, $gogs->token); + + if($result === false) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gogs->hostError)))); + if(!$result) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gogs->tokenLimit)))); + + return true; + } + + /** + * Bind gogs user to zentao users. + * + * @param int $gogsID + * @access public + * @return void + */ + public function bindUser($gogsID) + { + $zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account'); + $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter'); + + if($_POST) + { + $this->gogs->bindUser($gogsID); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer)); + } + + $this->view->title = $this->lang->gogs->bindUser; + $this->view->userPairs = $userPairs; + $this->view->gogsUsers = $this->gogs->apiGetUsers($gogsID); + $this->view->bindedUsers = $this->gogs->getUserAccountIdPairs($gogsID); + $this->view->matchedResult = $this->gogs->getMatchedUsers($gogsID, $this->view->gogsUsers, $zentaoUsers); + $this->display(); + } + + /** + * Ajax getProjectBranches + * + * @param int $gogsID + * @param string $project + * @access public + * @return void + */ + public function ajaxGetProjectBranches($gogsID, $project) + { + if(!$gogsID or !$project) return $this->send(array('message' => array())); + + $project = urldecode(base64_decode($project)); + $branches = $this->gogs->apiGetBranches($gogsID, $project); + $options = ""; + foreach($branches as $branch) + { + $options .= ""; + } + $this->send($options); + } +} diff --git a/module/gogs/css/browse.css b/module/gogs/css/browse.css new file mode 100644 index 0000000000..cb15b6808d --- /dev/null +++ b/module/gogs/css/browse.css @@ -0,0 +1,2 @@ +.c-id {width: 60px;} +.c-name {width: 200px;} diff --git a/module/gogs/css/common.css b/module/gogs/css/common.css new file mode 100644 index 0000000000..ad50c2a1d2 --- /dev/null +++ b/module/gogs/css/common.css @@ -0,0 +1,2 @@ +#publicTip {padding-left: 10px;} +.table-form>tbody>tr>th {width: 110px;} diff --git a/module/gogs/lang/de.php b/module/gogs/lang/de.php new file mode 100644 index 0000000000..68f32e3bab --- /dev/null +++ b/module/gogs/lang/de.php @@ -0,0 +1,36 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = 'Gogs Browse'; +$lang->gogs->search = 'Search'; +$lang->gogs->create = 'Create Gogs'; +$lang->gogs->edit = 'Edit Gogs'; +$lang->gogs->view = 'View Gogs'; +$lang->gogs->delete = 'Delete Gogs'; +$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?'; +$lang->gogs->bindUser = 'Bind User'; +$lang->gogs->gogsAvatar = 'Avatar'; +$lang->gogs->gogsAccount = 'Gogs Account'; +$lang->gogs->gogsEmail = 'Email'; +$lang->gogs->zentaoAccount = 'Zentao Account'; +$lang->gogs->bindingStatus = 'Binding Status'; +$lang->gogs->notBind = 'Not bind'; +$lang->gogs->binded = 'Binded'; +$lang->gogs->bindDynamic = '%s and Zentao user %s'; + +$lang->gogs->browseAction = 'Gogs List'; +$lang->gogs->deleteAction = 'Delete Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "Server Name"; +$lang->gogs->url = 'Server URL'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs."; +$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gogs->bindUserError = "Can not bind users repeatedly %s"; + +$lang->gogs->server = "Server List"; +$lang->gogs->lblCreate = 'Create Gogs Server'; +$lang->gogs->emptyError = " cannot be empty"; +$lang->gogs->createSuccess = "Create success"; diff --git a/module/gogs/lang/en.php b/module/gogs/lang/en.php new file mode 100644 index 0000000000..68f32e3bab --- /dev/null +++ b/module/gogs/lang/en.php @@ -0,0 +1,36 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = 'Gogs Browse'; +$lang->gogs->search = 'Search'; +$lang->gogs->create = 'Create Gogs'; +$lang->gogs->edit = 'Edit Gogs'; +$lang->gogs->view = 'View Gogs'; +$lang->gogs->delete = 'Delete Gogs'; +$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?'; +$lang->gogs->bindUser = 'Bind User'; +$lang->gogs->gogsAvatar = 'Avatar'; +$lang->gogs->gogsAccount = 'Gogs Account'; +$lang->gogs->gogsEmail = 'Email'; +$lang->gogs->zentaoAccount = 'Zentao Account'; +$lang->gogs->bindingStatus = 'Binding Status'; +$lang->gogs->notBind = 'Not bind'; +$lang->gogs->binded = 'Binded'; +$lang->gogs->bindDynamic = '%s and Zentao user %s'; + +$lang->gogs->browseAction = 'Gogs List'; +$lang->gogs->deleteAction = 'Delete Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "Server Name"; +$lang->gogs->url = 'Server URL'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs."; +$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gogs->bindUserError = "Can not bind users repeatedly %s"; + +$lang->gogs->server = "Server List"; +$lang->gogs->lblCreate = 'Create Gogs Server'; +$lang->gogs->emptyError = " cannot be empty"; +$lang->gogs->createSuccess = "Create success"; diff --git a/module/gogs/lang/fr.php b/module/gogs/lang/fr.php new file mode 100644 index 0000000000..68f32e3bab --- /dev/null +++ b/module/gogs/lang/fr.php @@ -0,0 +1,36 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = 'Gogs Browse'; +$lang->gogs->search = 'Search'; +$lang->gogs->create = 'Create Gogs'; +$lang->gogs->edit = 'Edit Gogs'; +$lang->gogs->view = 'View Gogs'; +$lang->gogs->delete = 'Delete Gogs'; +$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?'; +$lang->gogs->bindUser = 'Bind User'; +$lang->gogs->gogsAvatar = 'Avatar'; +$lang->gogs->gogsAccount = 'Gogs Account'; +$lang->gogs->gogsEmail = 'Email'; +$lang->gogs->zentaoAccount = 'Zentao Account'; +$lang->gogs->bindingStatus = 'Binding Status'; +$lang->gogs->notBind = 'Not bind'; +$lang->gogs->binded = 'Binded'; +$lang->gogs->bindDynamic = '%s and Zentao user %s'; + +$lang->gogs->browseAction = 'Gogs List'; +$lang->gogs->deleteAction = 'Delete Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "Server Name"; +$lang->gogs->url = 'Server URL'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs."; +$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gogs->bindUserError = "Can not bind users repeatedly %s"; + +$lang->gogs->server = "Server List"; +$lang->gogs->lblCreate = 'Create Gogs Server'; +$lang->gogs->emptyError = " cannot be empty"; +$lang->gogs->createSuccess = "Create success"; diff --git a/module/gogs/lang/vi.php b/module/gogs/lang/vi.php new file mode 100644 index 0000000000..6c7031c552 --- /dev/null +++ b/module/gogs/lang/vi.php @@ -0,0 +1,36 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = 'Gogs Browse'; +$lang->gogs->search = 'Search'; +$lang->gogs->create = 'Create Gogs'; +$lang->gogs->edit = 'Edit Gogs'; +$lang->gogs->view = 'View Gogs'; +$lang->gogs->delete = 'Delete Gogs'; +$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?'; +$lang->gogs->gogsAvatar = 'Avatar'; +$lang->gogs->bindUser = 'Bind User'; +$lang->gogs->gogsEmail = 'Email'; +$lang->gogs->gogsAccount = 'Gogs Account'; +$lang->gogs->zentaoAccount = 'Zentao Account'; +$lang->gogs->bindingStatus = 'Binding Status'; +$lang->gogs->notBind = 'Not bind'; +$lang->gogs->binded = 'Binded'; +$lang->gogs->bindDynamic = '%s and Zentao user %s'; + +$lang->gogs->browseAction = 'Gogs List'; +$lang->gogs->deleteAction = 'Delete Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "Server Name"; +$lang->gogs->url = 'Server URL'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs."; +$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gogs->bindUserError = "Can not bind users repeatedly %s"; + +$lang->gogs->server = "Server List"; +$lang->gogs->lblCreate = 'Create Gogs Server'; +$lang->gogs->emptyError = " cannot be empty"; +$lang->gogs->createSuccess = "Create success"; diff --git a/module/gogs/lang/zh-cn.php b/module/gogs/lang/zh-cn.php new file mode 100644 index 0000000000..0f263ae5e7 --- /dev/null +++ b/module/gogs/lang/zh-cn.php @@ -0,0 +1,36 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = '浏览Gogs'; +$lang->gogs->search = '搜索'; +$lang->gogs->create = '添加Gogs'; +$lang->gogs->edit = '编辑Gogs'; +$lang->gogs->view = '查看Gogs'; +$lang->gogs->delete = '删除Gogs'; +$lang->gogs->confirmDelete = '确认删除该Gogs吗?'; +$lang->gogs->bindUser = '绑定用户'; +$lang->gogs->gogsAvatar = '头像'; +$lang->gogs->gogsAccount = 'Gogs用户'; +$lang->gogs->gogsEmail = '邮箱'; +$lang->gogs->zentaoAccount = '禅道用户'; +$lang->gogs->bindingStatus = '绑定状态'; +$lang->gogs->notBind = '未绑定'; +$lang->gogs->binded = '已绑定'; +$lang->gogs->bindDynamic = '%s与禅道用户%s'; + +$lang->gogs->browseAction = 'Gogs列表'; +$lang->gogs->deleteAction = '删除Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "服务器名称"; +$lang->gogs->url = '服务器地址'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "Gogs Token权限不足。"; +$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问"; +$lang->gogs->bindUserError = "不能重复绑定用户 %s"; + +$lang->gogs->server = "服务器列表"; +$lang->gogs->lblCreate = '添加Gogs服务器'; +$lang->gogs->emptyError = "不能为空"; +$lang->gogs->createSuccess = "创建成功"; diff --git a/module/gogs/lang/zh-tw.php b/module/gogs/lang/zh-tw.php new file mode 100644 index 0000000000..c7e79e5013 --- /dev/null +++ b/module/gogs/lang/zh-tw.php @@ -0,0 +1,33 @@ +gogs = new stdclass; +$lang->gogs->common = 'Gogs'; +$lang->gogs->browse = '浏览Gogs'; +$lang->gogs->search = '搜索'; +$lang->gogs->create = '添加Gogs'; +$lang->gogs->edit = '编辑Gogs'; +$lang->gogs->view = '查看Gogs'; +$lang->gogs->delete = '删除Gogs'; +$lang->gogs->confirmDelete = '确认删除该Gogs吗?'; +$lang->gogs->bindUser = '绑定用户'; +$lang->gogs->gogsAccount = 'Gogs用户'; +$lang->gogs->zentaoAccount = '禅道用户'; +$lang->gogs->bindingStatus = '绑定状态'; +$lang->gogs->notBind = '未绑定'; +$lang->gogs->binded = '已绑定'; +$lang->gogs->bindDynamic = '%s与禅道用户%s'; + +$lang->gogs->browseAction = 'Gogs列表'; +$lang->gogs->deleteAction = '删除Gogs'; + +$lang->gogs->id = 'ID'; +$lang->gogs->name = "服务器名称"; +$lang->gogs->url = '服务器地址'; +$lang->gogs->token = 'Token'; + +$lang->gogs->tokenLimit = "Gogs Token权限不足。"; +$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问"; + +$lang->gogs->server = "服务器列表"; +$lang->gogs->lblCreate = '添加Gogs服务器'; +$lang->gogs->emptyError = "不能为空"; +$lang->gogs->createSuccess = "创建成功"; diff --git a/module/gogs/model.php b/module/gogs/model.php new file mode 100644 index 0000000000..0034530825 --- /dev/null +++ b/module/gogs/model.php @@ -0,0 +1,607 @@ + + * @package product + * @version $Id: $ + * @link http://www.zentao.net + */ + +class gogsModel extends model +{ + + const HOOK_PUSH_EVENT = 'Push Hook'; + + /* Gitlab access level. */ + public $noAccess = 0; + public $developerAccess = 30; + public $maintainerAccess = 40; + + /** + * Get a gogs by id. + * + * @param int $id + * @access public + * @return object + */ + public function getByID($id) + { + return $this->loadModel('pipeline')->getByID($id); + } + + /** + * Get gogs list. + * + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getList($orderBy = 'id_desc', $pager = null) + { + $gogsList = $this->loadModel('pipeline')->getList('gogs', $orderBy, $pager); + + return $gogsList; + } + + /** + * Get gogs pairs. + * + * @access public + * @return array + */ + public function getPairs() + { + return $this->loadModel('pipeline')->getPairs('gogs'); + } + + /** + * Get gogs api base url by gogs id. + * + * @param int $gogsID + * @param bool $sudo + * @access public + * @return string + */ + public function getApiRoot($gogsID, $sudo = true) + { + $gogs = $this->getByID($gogsID); + if(!$gogs) return ''; + + $sudoParam = ''; + if($sudo == true and !$this->app->user->admin) + { + $openID = $this->getUserIDByZentaoAccount($gogsID, $this->app->user->account); + if($openID) $sudoParam = "&sudo={$openID}"; + } + + return rtrim($gogs->url, '/') . '/api/v1%s' . "?token={$gogs->token}" . $sudoParam; + } + + /** + * Create a gogs. + * + * @access public + * @return bool + */ + public function create() + { + return $this->loadModel('pipeline')->create('gogs'); + } + + /** + * Update a gogs. + * + * @param int $id + * @access public + * @return bool + */ + public function update($id) + { + return $this->loadModel('pipeline')->update($id); + } + + /** + * Bind users. + * + * @param int $gogsID + * @access public + * @return array + */ + public function bindUser($gogsID) + { + $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter'); + $users = $this->post->zentaoUsers; + $gogsNames = $this->post->gogsUserNames; + $accountList = array(); + $repeatUsers = array(); + foreach($users as $openID => $user) + { + if(empty($user)) continue; + if(isset($accountList[$user])) $repeatUsers[] = zget($userPairs, $user); + $accountList[$user] = $openID; + } + + if(count($repeatUsers)) + { + dao::$errors[] = sprintf($this->lang->gogs->bindUserError, join(',', $repeatUsers)); + return false; + } + + $user = new stdclass; + $user->providerID = $gogsID; + $user->providerType = 'gogs'; + + $oldUsers = $this->dao->select('*')->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->fetchAll('openID'); + foreach($users as $openID => $account) + { + $existAccount = isset($oldUsers[$openID]) ? $oldUsers[$openID] : ''; + + if($existAccount and $existAccount->account != $account) + { + $this->dao->delete() + ->from(TABLE_OAUTH) + ->where('openID')->eq($openID) + ->andWhere('providerType')->eq($user->providerType) + ->andWhere('providerID')->eq($user->providerID) + ->exec(); + $this->loadModel('action')->create('gogsuser', $gogsID, 'unbind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$existAccount->account]->realname)); + } + if(!$existAccount or $existAccount->account != $account) + { + if(!$account) continue; + $user->account = $account; + $user->openID = $openID; + $this->dao->insert(TABLE_OAUTH)->data($user)->exec(); + $this->loadModel('action')->create('gogsuser', $gogsID, 'bind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$account]->realname)); + } + } + } + + /** + * Api error handling. + * + * @param object $response + * @access public + * @return bool + */ + public function apiErrorHandling($response) + { + if(!empty($response->error)) + { + dao::$errors[] = $response->error; + return false; + } + if(!empty($response->message)) + { + if(is_string($response->message)) + { + $errorKey = array_search($response->message, $this->lang->gogs->apiError); + dao::$errors[] = $errorKey === false ? $response->message : zget($this->lang->gogs->errorLang, $errorKey); + } + else + { + foreach($response->message as $field => $fieldErrors) + { + if(is_string($fieldErrors)) + { + $errorKey = array_search($fieldErrors, $this->lang->gogs->apiError); + if($fieldErrors) dao::$errors[$field][] = $errorKey === false ? $fieldErrors : zget($this->lang->gogs->errorLang, $errorKey); + } + else + { + foreach($fieldErrors as $error) + { + $errorKey = array_search($error, $this->lang->gogs->apiError); + if($error) dao::$errors[$field][] = $errorKey === false ? $error : zget($this->lang->gogs->errorLang, $errorKey); + } + } + } + } + } + + if(!$response) dao::$errors[] = false; + return false; + } + + /** + * Check user access. + * + * @param int $gogsID + * @param int $projectID + * @param object $project + * @param string $maxRole + * @access public + * @return bool + */ + public function checkUserAccess($gogsID, $projectID = 0, $project = null, $groupIDList = array(), $maxRole = 'maintainer') + { + if($this->app->user->admin) return true; + + if($project == null) $project = $this->apiGetSingleProject($gogsID, $projectID); + if(!isset($project->id)) return false; + + $accessLevel = $this->config->gogs->accessLevel[$maxRole]; + + if(isset($project->permissions->project_access->access_level) and $project->permissions->project_access->access_level >= $accessLevel) return true; + if(isset($project->permissions->group_access->access_level) and $project->permissions->group_access->access_level >= $accessLevel) return true; + if(!empty($project->shared_with_groups)) + { + if(empty($groupIDList)) + { + $groups = $this->apiGetGroups($gogsID, 'name_asc', $maxRole); + foreach($groups as $group) $groupIDList[] = $group->id; + } + + foreach($project->shared_with_groups as $group) + { + if($group->group_access_level < $accessLevel) continue; + if(in_array($group->group_id, $groupIDList)) return true; + } + } + + return false; + } + + /** + * Check token access. + * + * @param string $url + * @param string $token + * @access public + * @return void + */ + public function checkTokenAccess($url = '', $token = '') + { + $apiRoot = rtrim($url, '/') . '/api/v1%s' . "?token={$token}"; + $url = sprintf($apiRoot, "/admin/users") . "&limit=1"; + $httpData = commonModel::httpWithHeader($url); + $users = json_decode($httpData['body']); + if(empty($users)) return false; + if(isset($users->message) or isset($users->error)) return null; + return true; + } + + /** + * Get Gogs id list by user account. + * + * @param string $account + * @access public + * @return array + */ + public function getGogsListByAccount($account = '') + { + if(!$account) $account = $this->app->user->account; + + return $this->dao->select('providerID,openID')->from(TABLE_OAUTH) + ->where('providerType')->eq('gogs') + ->andWhere('account')->eq($account) + ->fetchPairs('providerID'); + } + + /** + * Get zentao account gogs user id pairs of one gogs. + * + * @param int $gogsID + * @access public + * @return array + */ + public function getUserAccountIdPairs($gogsID, $fields = 'account,openID') + { + return $this->dao->select($fields)->from(TABLE_OAUTH) + ->where('providerType')->eq('gogs') + ->andWhere('providerID')->eq($gogsID) + ->fetchPairs(); + } + + /** + * Get gogs user id by zentao account. + * + * @param int $gogsID + * @param string $zentaoAccount + * @access public + * @return array + */ + public function getUserIDByZentaoAccount($gogsID, $zentaoAccount) + { + return $this->dao->select('openID')->from(TABLE_OAUTH) + ->where('providerType')->eq('gogs') + ->andWhere('providerID')->eq($gogsID) + ->andWhere('account')->eq($zentaoAccount) + ->fetch('openID'); + } + + /** + * Get matched gogs users. + * + * @param int $gogsID + * @param array $gogsUsers + * @param array $zentaoUsers + * @access public + * @return array + */ + public function getMatchedUsers($gogsID, $gogsUsers, $zentaoUsers) + { + $matches = new stdclass; + foreach($gogsUsers as $gogsUser) + { + foreach($zentaoUsers as $zentaoUser) + { + if($gogsUser->account == $zentaoUser->account) $matches->accounts[$gogsUser->account][] = $zentaoUser->account; + if($gogsUser->realname == $zentaoUser->realname) $matches->names[$gogsUser->realname][] = $zentaoUser->account; + if($gogsUser->email == $zentaoUser->email) $matches->emails[$gogsUser->email][] = $zentaoUser->account; + } + } + + $bindedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account'); + $matchedUsers = array(); + foreach($gogsUsers as $gogsUser) + { + if(isset($bindedUsers[$gogsUser->account])) + { + $gogsUser->zentaoAccount = $bindedUsers[$gogsUser->account]; + $matchedUsers[] = $gogsUser; + continue; + } + + $matchedZentaoUsers = array(); + if(isset($matches->accounts[$gogsUser->account])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->accounts[$gogsUser->account]); + if(isset($matches->emails[$gogsUser->email])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->emails[$gogsUser->email]); + if(isset($matches->names[$gogsUser->realname])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->names[$gogsUser->realname]); + + $matchedZentaoUsers = array_unique($matchedZentaoUsers); + if(count($matchedZentaoUsers) == 1) + { + $gogsUser->zentaoAccount = current($matchedZentaoUsers); + $matchedUsers[] = $gogsUser; + } + } + + return $matchedUsers; + } + + /** + * Get project by api. + * + * @param int $gogsID + * @param int $projectID + * @access public + * @return void + */ + public function apiGetSingleProject($gogsID, $projectID) + { + $apiRoot = $this->getApiRoot($gogsID); + if(!$apiRoot) return array(); + + $url = sprintf($apiRoot, "/repos/$projectID"); + $project = json_decode(commonModel::http($url)); + if(isset($project->name)) + { + $project->name_with_namespace = $project->full_name; + $project->path_with_namespace = $project->full_name; + $project->http_url_to_repo = $project->html_url; + $project->name_with_namespace = $project->full_name; + + $gogs = $this->getByID($gogsID); + $oauth = "oauth2:{$gogs->token}@"; + $project->tokenCloneUrl = preg_replace('/(http(s)?:\/\/)/', "\$1$oauth", $project->html_url); + } + + return $project; + } + + /** + * Get projects by api. + * + * @param int $gogsID + * @param bool $sudo + * @access public + * @return array + */ + public function apiGetProjects($gogsID, $sudo = true) + { + $apiRoot = $this->getApiRoot($gogsID, $sudo); + if(!$apiRoot) return array(); + + $url = sprintf($apiRoot, "/repos/search"); + $allResults = array(); + for($page = 1; true; $page++) + { + $results = json_decode(commonModel::http($url . "&page={$page}&limit=50")); + if(!is_array($results->data)) break; + if(!empty($results->data)) $allResults = array_merge($allResults, $results->data); + if(count($results->data) < 50) break; + } + + return $allResults; + } + + /** + * Get gogs user list. + * + * @param int $gogsID + * @param bool $onlyLinked + * @access public + * @return array + */ + public function apiGetUsers($gogsID, $onlyLinked = false) + { + $response = array(); + $apiRoot = $this->getApiRoot($gogsID); + + for($page = 1; true; $page++) + { + $url = sprintf($apiRoot, "/users/search") . "&page={$page}&limit=50"; + $result = json_decode(commonModel::http($url)); + if(empty($result->data)) break; + + $response = array_merge($response, $result->data); + $page += 1; + } + + if(empty($response)) return array(); + + /* Get linked users. */ + $linkedUsers = array(); + if($onlyLinked) $linkedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account'); + + $users = array(); + foreach($response as $gogsUser) + { + if($onlyLinked and !isset($linkedUsers[$gogsUser->id])) continue; + + $user = new stdclass; + $user->id = $gogsUser->id; + $user->realname = $gogsUser->full_name ? $gogsUser->full_name : $gogsUser->username; + $user->account = $gogsUser->username; + $user->email = zget($gogsUser, 'email', ''); + $user->avatar = $gogsUser->avatar_url; + $user->createdAt = zget($gogsUser, 'created', ''); + $user->lastActivityOn = zget($gogsUser, 'last_login', ''); + + $users[] = $user; + } + + return $users; + } + + /** + * Get project repository branches by api. + * + * @param int $gogsID + * @param string $project + * @access public + * @return object + */ + public function apiGetBranches($gogsID, $project, $pager = null) + { + $url = sprintf($this->getApiRoot($gogsID), "/repos/{$project}/branches"); + $allResults = array(); + for($page = 1; true; $page++) + { + $results = json_decode(commonModel::http($url . "&page={$page}&limit=50")); + if(!is_array($results)) break; + if(!empty($results)) $allResults = array_merge($allResults, $results); + if(count($results) < 100) break; + } + + return $allResults; + } + + /** + * Get Forks of a project by API. + * + * @param int $gogsID + * @param string $projectID + * @access public + * @return object + */ + public function apiGetForks($gogsID, $projectID) + { + $url = sprintf($this->getApiRoot($gogsID), "/repos/$projectID/forks"); + return json_decode(commonModel::http($url)); + } + + /** + * Get upstream project by API. + * + * @param int $gogsID + * @param string $projectID + * @access public + * @return void + */ + public function apiGetUpstream($gogsID, $projectID) + { + $currentProject = $this->apiGetSingleProject($gogsID, $projectID); + if(isset($currentProject->parent->full_name)) return $currentProject->parent->full_name; + return array(); + } + + /** + * Get branches. + * + * @param int $gogsID + * @param string $project + * @access public + * @return array + */ + public function getBranches($gogsID, $project) + { + $rawBranches = $this->apiGetBranches($gogsID, $project); + + $branches = array(); + foreach($rawBranches as $branch) $branches[] = $branch->name; + + return $branches; + } + + /** + * Get gogs user id and realname pairs of one gogs. + * + * @param int $gogsID + * @access public + * @return array + */ + public function getUserIdRealnamePairs($gogsID) + { + return $this->dao->select('oauth.openID as openID,user.realname as realname') + ->from(TABLE_OAUTH)->alias('oauth') + ->leftJoin(TABLE_USER)->alias('user') + ->on("oauth.account = user.account") + ->where('providerType')->eq('gogs') + ->andWhere('providerID')->eq($gogsID) + ->fetchPairs(); + } + + /** + * Get single branch by API. + * + * @param int $gogsID + * @param string $project + * @param string $branchName + * @access public + * @return object + */ + public function apiGetSingleBranch($gogsID, $project, $branchName) + { + $url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branchName"); + $branch = json_decode(commonModel::http($url)); + if($branch) + { + $gogs = $this->getByID($gogsID); + $branch->web_url = "{$gogs->url}/$project/src/branch/$branchName"; + } + + return $branch; + } + + /** + * Get protect branches of one project. + * + * @param int $gogsID + * @param string $project + * @param string $keyword + * @access public + * @return array + */ + public function apiGetBranchPrivs($gogsID, $project, $keyword = '') + { + $keyword = urlencode($keyword); + $url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branch_protections"); + $branches = json_decode(commonModel::http($url)); + + if(!is_array($branches)) return $branches; + + $newBranches = array(); + foreach($branches as $branch) + { + $branch->name = $branch->branch_name; + if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[] = $branch; + } + + return $newBranches; + } +} diff --git a/module/gogs/view/binduser.html.php b/module/gogs/view/binduser.html.php new file mode 100644 index 0000000000..b06735dd9b --- /dev/null +++ b/module/gogs/view/binduser.html.php @@ -0,0 +1,85 @@ + + * @package gogs + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+

gogs->bindUser;?>

+
+
+
+ + + + + + + + + + + + + zentaoAccount)) continue;?> + account]", $gogsUser->realname);?> + + + + + + + + + + zentaoAccount)) continue;?> + account]", $gogsUser->realname);?> + + + + + + + + + + + + + + +
gogs->gogsAvatar;?>gogs->gogsAccount;?>gogs->gogsEmail;?>gogs->zentaoAccount;?>gogs->bindingStatus;?>
avatar, "height=40");?> + realname;?> +
+ account;?> +
email;?>account]", $userPairs, '', "class='form-control select chosen'" );?>gogs->notBind;?>
avatar, "height=40");?> + realname;?> +
+ account;?> +
email;?>account]", $userPairs, $gogsUser->zentaoAccount, "class='form-control select chosen'" );?> + zentaoAccount])):?> + zentaoAccount, '');?> + + gogs->binded;?> + + ' . $lang->gogs->bindedError . '';?> + + + gogs->notBind;?> + +
+ + goback, '', 'class="btn btn-wide"');?> +
+
+
+
+ diff --git a/module/gogs/view/browse.html.php b/module/gogs/view/browse.html.php new file mode 100644 index 0000000000..d925058381 --- /dev/null +++ b/module/gogs/view/browse.html.php @@ -0,0 +1,73 @@ + + * @package gogs + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
+

+ noData;?> + + createLink('gogs', 'create'), " " . $lang->gogs->create, '', "class='btn btn-info'");?> + +

+
+ +
+
+ + + + recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> + + + + + + + + $gogs): ?> + + + + + + + + +
gogs->id);?>gogs->name);?>gogs->url);?>actions;?>
+ + ">name;?> + + name;?> + + url, $gogs->url, '_target');?> + isBindUser); + common::printIcon('gogs', 'delete', "gogsID=$id", '', 'list', 'trash', 'hiddenwin'); + ?> +
+ + + +
+
+ + diff --git a/module/gogs/view/create.html.php b/module/gogs/view/create.html.php new file mode 100644 index 0000000000..df7c376c66 --- /dev/null +++ b/module/gogs/view/create.html.php @@ -0,0 +1,45 @@ + + * @package gogs + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+
+
+

gogs->lblCreate;?>

+
+
+ + + + + + + + + + + + + + + + + +
gogs->name;?>
gogs->url;?>
gogs->token;?>
+ +
+
+
+
+
+ diff --git a/module/gogs/view/edit.html.php b/module/gogs/view/edit.html.php new file mode 100644 index 0000000000..aafb2fe439 --- /dev/null +++ b/module/gogs/view/edit.html.php @@ -0,0 +1,45 @@ + + * @package gogs + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+
+
+

gogs->edit;?>

+
+
+ + + + + + + + + + + + + + + + + +
gogs->name;?>name) ? $gogs->name : '', "class='form-control'");?>
gogs->url;?>url) ? $gogs->url : '', "class='form-control'");?>
gogs->token;?>token) ? $gogs->token : '', "class='form-control'");?>
+ +
+
+
+
+
+ diff --git a/module/gogs/view/view.html.php b/module/gogs/view/view.html.php new file mode 100644 index 0000000000..66cb881716 --- /dev/null +++ b/module/gogs/view/view.html.php @@ -0,0 +1,37 @@ + + * @package GitLab + * @version $Id: view.html.php 4728 2013-05-03 06:14:34Z david18810279601@gmail.com $ + * @link http://www.zentao.net + * */ +?> + + + +
+
+
+
+
gogs->url;?>
+
url, $gogs->url, '_target');?>
+
+
+
+
+
+ From f3044011d8a9b731cb88796112d224ec0f2e3bdb Mon Sep 17 00:00:00 2001 From: liyuchun <563917701@qq.com> Date: Mon, 1 Aug 2022 05:58:24 +0000 Subject: [PATCH 002/106] * Finish task #62870. --- config/zentaopms.php | 1 + module/action/config.php | 3 ++- module/action/lang/de.php | 6 ++++++ module/action/lang/en.php | 6 ++++++ module/action/lang/fr.php | 6 ++++++ module/action/lang/vi.php | 6 ++++++ module/action/lang/zh-cn.php | 6 ++++++ module/action/model.php | 4 ++-- module/common/lang/menu.php | 4 +++- module/gogs/model.php | 6 +++--- module/group/lang/resource.php | 19 ++++++++++++++++++- 11 files changed, 59 insertions(+), 8 deletions(-) diff --git a/config/zentaopms.php b/config/zentaopms.php index 646f396d0a..e995bd0b47 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -373,6 +373,7 @@ $config->objectTables['kanbangroup'] = TABLE_KANBANGROUP; $config->objectTables['kanbancard'] = TABLE_KANBANCARD; $config->objectTables['sonarqube'] = TABLE_PIPELINE; $config->objectTables['gitea'] = TABLE_PIPELINE; +$config->objectTables['gogs'] = TABLE_PIPELINE; $config->objectTables['gitlab'] = TABLE_PIPELINE; $config->objectTables['jebkins'] = TABLE_PIPELINE; $config->objectTables['stage'] = TABLE_STAGE; diff --git a/module/action/config.php b/module/action/config.php index 000cdcd5cf..2565ee1d5d 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -44,6 +44,7 @@ $config->action->objectNameFields['kanbancard'] = 'name'; $config->action->objectNameFields['sonarqube'] = 'name'; $config->action->objectNameFields['gitlab'] = 'name'; $config->action->objectNameFields['gitea'] = 'name'; +$config->action->objectNameFields['gogs'] = 'name'; $config->action->objectNameFields['stage'] = 'name'; $config->action->objectNameFields['apistruct'] = 'name'; $config->action->objectNameFields['repo'] = 'name'; @@ -62,7 +63,7 @@ $config->action->majorList['execution'] = array('opened', 'edited'); $config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,'; $config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,'; -$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,'; +$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,'; $config->action->preferredTypeNum = 10; diff --git a/module/action/lang/de.php b/module/action/lang/de.php index dd04ece590..956f5e9854 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -128,6 +128,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist'; $lang->action->objectTypes['pipeline'] = 'GitLib'; $lang->action->objectTypes['gitlab'] = 'GitLab Server'; $lang->action->objectTypes['gitea'] = 'Gitea Server'; +$lang->action->objectTypes['gogs'] = 'Gogs Server'; $lang->action->objectTypes['jenkins'] = 'Jenkins'; $lang->action->objectTypes['mr'] = 'Merge Request'; $lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; @@ -138,6 +139,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; $lang->action->objectTypes['giteauser'] = 'Gitea User'; +$lang->action->objectTypes['gogsuser'] = 'Gogs User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -649,6 +651,10 @@ $lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server'; $lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server'; $lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server'; +$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server'; +$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server'; +$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server'; + /* Generate the corresponding object link. */ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; $lang->action->label->productplan = 'Plan|productplan|view|productID=%s'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 1a927d1e7e..1a90833b50 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -128,6 +128,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist'; $lang->action->objectTypes['pipeline'] = 'GitLab Server'; $lang->action->objectTypes['gitlab'] = 'GitLab Server'; $lang->action->objectTypes['gitea'] = 'Gitea Server'; +$lang->action->objectTypes['gogs'] = 'Gogs Server'; $lang->action->objectTypes['jenkins'] = 'Jenkins'; $lang->action->objectTypes['mr'] = 'Merge Request'; $lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; @@ -138,6 +139,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; $lang->action->objectTypes['giteauser'] = 'Gitea User'; +$lang->action->objectTypes['gogsuser'] = 'Gogs User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -649,6 +651,10 @@ $lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server'; $lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server'; $lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server'; +$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server'; +$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server'; +$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server'; + /* Generate the corresponding object link. */ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; $lang->action->label->productplan = 'Plan|productplan|view|productID=%s'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 534a5cbe99..c4398b40a8 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -128,6 +128,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist'; $lang->action->objectTypes['pipeline'] = 'GitLib'; $lang->action->objectTypes['gitlab'] = 'GitLab Server'; $lang->action->objectTypes['gitea'] = 'Gitea Server'; +$lang->action->objectTypes['gogs'] = 'Gogs Server'; $lang->action->objectTypes['jenkins'] = 'Jenkins'; $lang->action->objectTypes['mr'] = 'Merge Request'; $lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; @@ -138,6 +139,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; $lang->action->objectTypes['giteauser'] = 'Gitea User'; +$lang->action->objectTypes['gogsuser'] = 'Gogs User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -649,6 +651,10 @@ $lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server'; $lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server'; $lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server'; +$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server'; +$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server'; +$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server'; + /* Generate the corresponding object link. */ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; $lang->action->label->productplan = 'Plan|productplan|view|productID=%s'; diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index 09f6928001..3829a7b131 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -102,6 +102,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist'; $lang->action->objectTypes['pipeline'] = 'GitLib'; $lang->action->objectTypes['gitlab'] = 'GitLab Server'; $lang->action->objectTypes['gitea'] = 'Gitea Server'; +$lang->action->objectTypes['gogs'] = 'Gogs Server'; $lang->action->objectTypes['jenkins'] = 'Jenkins'; $lang->action->objectTypes['mr'] = 'Merge Request'; $lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; @@ -112,6 +113,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; $lang->action->objectTypes['giteauser'] = 'Gitea User'; +$lang->action->objectTypes['gogsuser'] = 'Gogs User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -507,6 +509,10 @@ $lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server'; $lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server'; $lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server'; +$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server'; +$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server'; +$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server'; + /* Generate the corresponding object link. */ global $config; $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index f3a4d1a7cc..71bc76ac43 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -128,6 +128,7 @@ $lang->action->objectTypes['whitelist'] = '白名单'; $lang->action->objectTypes['pipeline'] = 'GitLab服务器'; $lang->action->objectTypes['gitlab'] = 'GitLab服务器'; $lang->action->objectTypes['gitea'] = 'Gitea服务器'; +$lang->action->objectTypes['gogs'] = 'Gogs服务器'; $lang->action->objectTypes['jenkins'] = 'Jenkins'; $lang->action->objectTypes['mr'] = '合并请求'; $lang->action->objectTypes['gitlabproject'] = 'GitLab项目'; @@ -138,6 +139,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保护分支'; $lang->action->objectTypes['gitlabtag'] = 'GitLab标签'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab标签保护'; $lang->action->objectTypes['giteauser'] = 'Gitea用户'; +$lang->action->objectTypes['gogsuser'] = 'Gogs用户'; $lang->action->objectTypes['kanbanspace'] = '看板空间'; $lang->action->objectTypes['kanban'] = '看板'; $lang->action->objectTypes['kanbanregion'] = '看板区域'; @@ -649,6 +651,10 @@ $lang->action->dynamicAction->gitea['created'] = '创建Gitea服务器'; $lang->action->dynamicAction->gitea['edited'] = '编辑Gitea服务器'; $lang->action->dynamicAction->gitea['deleted'] = '删除Gitea服务器'; +$lang->action->dynamicAction->gogs['created'] = '创建Gogs服务器'; +$lang->action->dynamicAction->gogs['edited'] = '编辑Gogs服务器'; +$lang->action->dynamicAction->gogs['deleted'] = '删除Gogs服务器'; + /* 用来生成相应对象的链接。*/ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; $lang->action->label->productplan = "计划|productplan|view|productID=%s"; diff --git a/module/action/model.php b/module/action/model.php index 695c954c7d..7ae41b46a1 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -1277,8 +1277,8 @@ class actionModel extends model /* If action type is login or logout, needn't link. */ if($actionType == 'svncommited' or $actionType == 'gitcommited') $action->actor = zget($commiters, $action->actor); - /* Get gitlab or gitea objectname. */ - if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea')) $action->objectName = $action->extra; + /* Get gitlab, gitea or gogs objectname. */ + if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea' or substr($objectType, 0, 4) == 'gogs')) $action->objectName = $action->extra; /* Other actions, create a link. */ $this->setObjectLink($action, $deptUsers); diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 67e1345892..a42770916b 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -408,7 +408,7 @@ $lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|brows $lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse|repoID=%s"); $lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse|repoID=%s", 'subModule' => 'compile,job'); $lang->devops->menu->app = array('link' => "{$lang->app->common}|app|serverlink|%s"); -$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea', 'alias' => 'setrules,create,edit'); +$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea,gogs', 'alias' => 'setrules,create,edit'); $lang->devops->menuOrder[5] = 'code'; $lang->devops->menuOrder[10] = 'mr'; @@ -421,6 +421,7 @@ $lang->devops->dividerMenu = ',set,'; $lang->devops->menu->set['subMenu'] = new stdclass(); $lang->devops->menu->set['subMenu']->repo = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit'); $lang->devops->menu->set['subMenu']->gitlab = array('link' => 'GitLab|gitlab|browse', 'subModule' => 'gitlab'); +$lang->devops->menu->set['subMenu']->gogs = array('link' => 'Gogs|gogs|browse', 'subModule' => 'gogs'); $lang->devops->menu->set['subMenu']->gitea = array('link' => 'Gitea|gitea|browse', 'subModule' => 'gitea'); $lang->devops->menu->set['subMenu']->jenkins = array('link' => 'Jenkins|jenkins|browse', 'subModule' => ''); $lang->devops->menu->set['subMenu']->sonarqube = array('link' => 'SonarQube|sonarqube|browse', 'subModule' => 'sonarqube'); @@ -658,6 +659,7 @@ $lang->navGroup->job = 'devops'; $lang->navGroup->jenkins = 'devops'; $lang->navGroup->mr = 'devops'; $lang->navGroup->gitlab = 'devops'; +$lang->navGroup->gogs = 'devops'; $lang->navGroup->gitea = 'devops'; $lang->navGroup->sonarqube = 'devops'; $lang->navGroup->sonarqubeproject = 'devops'; diff --git a/module/gogs/model.php b/module/gogs/model.php index 0034530825..a59d916237 100644 --- a/module/gogs/model.php +++ b/module/gogs/model.php @@ -257,10 +257,10 @@ class gogsModel extends model public function checkTokenAccess($url = '', $token = '') { $apiRoot = rtrim($url, '/') . '/api/v1%s' . "?token={$token}"; - $url = sprintf($apiRoot, "/admin/users") . "&limit=1"; + $url = sprintf($apiRoot, "/user"); $httpData = commonModel::httpWithHeader($url); - $users = json_decode($httpData['body']); - if(empty($users)) return false; + $user = json_decode($httpData['body']); + if(empty($user)) return false; if(isset($users->message) or isset($users->error)) return null; return true; } diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index c535452c03..de24679028 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -69,7 +69,8 @@ $lang->moduleOrder[215] = 'message'; $lang->moduleOrder[220] = 'gitlab'; $lang->moduleOrder[225] = 'mr'; $lang->moduleOrder[230] = 'app'; -$lang->moduleOrder[235] = 'gitea'; +$lang->moduleOrder[235] = 'gogs'; +$lang->moduleOrder[240] = 'gitea'; $lang->resource = new stdclass(); @@ -1386,6 +1387,22 @@ $lang->gitlab->methodOrder[145] = 'browseTag'; $lang->gitlab->methodOrder[150] = 'createTag'; $lang->gitlab->methodOrder[155] = 'deleteTag'; +/* Gogs. */ +$lang->resource->gogs = new stdclass(); +$lang->resource->gogs->browse = 'browse'; +$lang->resource->gogs->create = 'create'; +$lang->resource->gogs->edit = 'edit'; +$lang->resource->gogs->view = 'view'; +$lang->resource->gogs->delete = 'delete'; +$lang->resource->gogs->bindUser = 'bindUser'; + +$lang->gogs->methodOrder[5] = 'browse'; +$lang->gogs->methodOrder[10] = 'create'; +$lang->gogs->methodOrder[15] = 'edit'; +$lang->gogs->methodOrder[20] = 'view'; +$lang->gogs->methodOrder[25] = 'delete'; +$lang->gogs->methodOrder[30] = 'bindUser'; + /* Gitea. */ $lang->resource->gitea = new stdclass(); $lang->resource->gitea->browse = 'browse'; From 4b1dde8c7e5d7adcc99f37af3df9770712995efa Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 15:40:55 +0800 Subject: [PATCH 003/106] * Modify gogs repo. --- lib/scm/gitea.class.php | 2 +- lib/scm/gitrepo.class.php | 2 +- lib/scm/gogs.class.php | 692 +++++++++++++++++++++++++++++ module/git/model.php | 22 +- module/gogs/model.php | 152 ++----- module/mr/config.php | 2 +- module/mr/control.php | 10 +- module/mr/js/create.js | 6 +- module/mr/model.php | 23 +- module/repo/config.php | 3 +- module/repo/control.php | 68 ++- module/repo/js/create.js | 9 +- module/repo/js/edit.js | 9 +- module/repo/lang/de.php | 1 + module/repo/lang/en.php | 1 + module/repo/lang/fr.php | 1 + module/repo/lang/vi.php | 1 + module/repo/lang/zh-cn.php | 1 + module/repo/model.php | 29 +- module/repo/view/create.html.php | 4 +- module/repo/view/edit.html.php | 4 +- module/repo/view/maintain.html.php | 2 +- module/upgrade/config.php | 4 +- 23 files changed, 871 insertions(+), 177 deletions(-) create mode 100644 lib/scm/gogs.class.php diff --git a/lib/scm/gitea.class.php b/lib/scm/gitea.class.php index 3e8709bd70..c61f1fa15b 100644 --- a/lib/scm/gitea.class.php +++ b/lib/scm/gitea.class.php @@ -551,7 +551,7 @@ class Gitea { if(!scm::checkRevision($revision)) return array(); - if($revision == 'HEAD' and $branch) $revision = $branch; + if($revision == 'HEAD' and $branch) $revision = 'origin/' . $branch; $revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision; $count = $count == 0 ? '' : "-n $count"; diff --git a/lib/scm/gitrepo.class.php b/lib/scm/gitrepo.class.php index aaafee2639..6bf5f0646a 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -540,7 +540,7 @@ class GitRepo { if(!scm::checkRevision($revision)) return array(); - if($revision == 'HEAD' and $branch) $revision = $branch; + if($revision == 'HEAD' and $branch) $revision = 'origin/' . $branch; $revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision; $count = $count == 0 ? '' : "-n $count"; diff --git a/lib/scm/gogs.class.php b/lib/scm/gogs.class.php new file mode 100644 index 0000000000..7ea7c81f88 --- /dev/null +++ b/lib/scm/gogs.class.php @@ -0,0 +1,692 @@ +client = $client; + $this->root = rtrim($root, DIRECTORY_SEPARATOR); + if(!realpath($this->root) and !empty($repo)) + { + global $app; + $project = $app->control->loadModel('gogs')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject); + if(isset($project->tokenCloneUrl)) + { + $cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $this->root . '"'; + exec($cmd); + } + } + + $branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : ''; + if($branch) + { + $branches = $this->branch(); + if(isset($branches[$branch])) $branch = "origin/$branch"; + } + $this->branch = $branch; + + chdir($this->root); + exec("{$this->client} config core.quotepath false"); + } + + /** + * List files. + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function ls($path, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return array(); + + $path = ltrim($path, DIRECTORY_SEPARATOR); + $sub = ''; + chdir($this->root); + if(!empty($path)) $sub = ":$path"; + if(!empty($this->branch))$revision = $this->branch; + execCmd(escapeCmd("$this->client pull")); + $cmd = escapeCmd("$this->client ls-tree -l $revision$sub"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); + + $infos = array(); + foreach($list as $entry) + { + list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry); + + /* Get commit info. */ + $pathName = ltrim($path . DIRECTORY_SEPARATOR . $name, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client log -1 $this->branch -- $pathName"); + $commit = execCmd($cmd, 'array'); + $logs = $this->parseLog($commit); + + if($size > 1024 * 1024) + { + $size = round($size / (1024 * 1024), 2) . 'MB'; + } + else if($size > 1024) + { + $size = round($size / 1024, 2) . 'KB'; + } + else + { + $size .= 'Bytes'; + } + + $info = new stdClass(); + $info->name = $name; + $info->kind = $kind == 'tree' ? 'dir' : 'file'; + $info->revision = $logs ? $logs[0]->revision : $revision; + $info->size = $size; + $info->account = $logs ? $logs[0]->committer : ''; + $info->date = $logs ? $logs[0]->time : ''; + $info->comment = $logs ? $logs[0]->comment : ''; + $infos[] = $info; + unset($info); + } + + /* Sort by kind */ + foreach($infos as $key => $info) $kinds[$key] = $info->kind; + if($infos) array_multisort($kinds, SORT_ASC, $infos); + + return $infos; + } + + /** + * Get tags + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function tags($path, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return array(); + + 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) + { + if(!$tag) unset($list[$key]); + } + + return $list; + } + + /** + * Get branch. + * + * @access public + * @return array + */ + public function branch() + { + 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. */ + $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; + if($localBranch != $defaultBranch) $branches[$localBranch] = $localBranch; + } + + asort($branches); + if($defaultBranch) $branches = array($defaultBranch => $defaultBranch) + $branches; + + return $branches; + } + + /** + * Get last log. + * + * @param string $path + * @param int $count + * @access public + * @return array + */ + public function getLastLog($path, $count = 10) + { + $path = ltrim($path, DIRECTORY_SEPARATOR); + $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 + * + * @param string $path + * @param string $fromRevision + * @param string $toRevision + * @param int $count + * @access public + * @return array + */ + public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0) + { + if(!scm::checkRevision($fromRevision)) return array(); + if(!scm::checkRevision($toRevision)) return array(); + + $path = ltrim($path, DIRECTORY_SEPARATOR); + $count = $count == 0 ? '' : "-n $count"; + /* compatible with svn. */ + if($fromRevision == 'HEAD' and $this->branch) $fromRevision = $this->branch; + if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch; + if($fromRevision === $toRevision) + { + $logs = array(); + chdir($this->root); + + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 -1 $fromRevision -- $path"), 'array'); + $logs = $this->parseLog($list); + return $logs; + } + + if(!$fromRevision) + { + $revisions = " $toRevision"; + } + else + { + $revisions = "$fromRevision..$toRevision"; + } + chdir($this->root); + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 $count $revisions -- $path"), 'array'); + $logs = $this->parseLog($list); + + return $logs; + } + + /** + * Blame file + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function blame($path, $revision) + { + 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; + } + + /** + * Diff file. + * + * @param string $path + * @param string $fromRevision + * @param string $toRevision + * @param string $extra + * @access public + * @return array + */ + 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(); + + $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; + } + + /** + * Cat file. + * + * @param string $entry + * @param string $revision + * @access public + * @return string + */ + public function cat($entry, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return false; + + chdir($this->root); + if($revision == 'HEAD' and $this->branch) $revision = $this->branch; + $cmd = escapeCmd("$this->client show $revision:$entry"); + $content = execCmd($cmd); + if(is_array($content)) $content = implode("\n", $content); + return $content; + } + + /** + * Get info. + * + * @param string $entry + * @param string $revision + * @access public + * @return object + */ + public function info($entry, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return false; + + chdir($this->root); + if($revision == 'HEAD' and $this->branch) $revision = $this->branch; + $path = ltrim($entry, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client ls-tree $revision -- $path"); + $result = execCmd($cmd); + $kind = ''; + if($result) + { + $results = explode("\n", trim($result)); + if(count($results) >= 2) + { + $kind = 'dir'; + } + else + { + list($mode, $type) = explode(' ', $results[0]); + $kind = $type == 'tree' ? 'dir' : 'file'; + } + } + + $list = execCmd(escapeCmd("$this->client log -1 $revision --pretty=format:%H -- $path"), 'array'); + $revision = $list[0]; + $info = new stdclass(); + $info->kind = $kind; + $info->path = $entry; + $info->revision = $revision; + $info->root = $this->root; + return $info; + } + + /** + * Exec git cmd. + * + * @param string $cmd + * @access public + * @return array + */ + public function exec($cmd) + { + chdir($this->root); + return execCmd(escapeCmd("$this->client $cmd"), 'array'); + } + + /** + * Parse diff. + * + * @param array $lines + * @access public + * @return array + */ + public function parseDiff($lines) + { + if(empty($lines)) return array(); + $diffs = array(); + $num = count($lines); + $endLine = end($lines); + if(strpos($endLine, '\ No newline at end of file') === 0) $num -= 1; + + $newFile = false; + $allFiles = array(); + for($i = 0; $i < $num; $i ++) + { + $diffFile = new stdclass(); + if(strpos($lines[$i], "diff --git ") === 0) + { + $fileInfo = explode(' ',$lines[$i]); + $fileName = substr($fileInfo[2], strpos($fileInfo[2], '/') + 1); + + /* Prevent duplicate display of files. */ + if(in_array($fileName, $allFiles)) continue; + $allFiles[] = $fileName; + + $diffFile->fileName = $fileName; + for($i++; $i < $num; $i ++) + { + $diff = new stdclass(); + /* Fix bug #1757. */ + if($lines[$i] == '+++ /dev/null') $newFile = true; + if(strpos($lines[$i], '+++', 0) !== false) continue; + if(strpos($lines[$i], '---', 0) !== false) continue; + if(strpos($lines[$i], '======', 0) !== false) continue; + if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i])) + { + $startLines = trim(str_replace(array('@', '+', '-'), '', $lines[$i])); + list($oldStartLine, $newStartLine) = explode(' ', $startLines); + list($diff->oldStartLine) = explode(',', $oldStartLine); + list($diff->newStartLine) = explode(',', $newStartLine); + $oldCurrentLine = $diff->oldStartLine; + $newCurrentLine = $diff->newStartLine; + if($newFile) + { + $oldCurrentLine = $diff->newStartLine; + $newCurrentLine = $diff->oldStartLine; + } + $newLines = array(); + for($i++; $i < $num; $i ++) + { + if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i])) + { + $i --; + break; + } + if(strpos($lines[$i], "diff --git ") === 0) break; + + $line = $lines[$i]; + if(strpos($line, '\ No newline at end of file') === 0)continue; + $sign = empty($line) ? '' : $line[0]; + if($sign == '-' and $newFile) $sign = '+'; + $type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old'; + if($sign == '-' || $sign == '+') + { + $line = substr_replace($line, ' ', 1, 0); + if($newFile) $line = preg_replace('/^\-/', '+', $line); + } + + $newLine = new stdclass(); + $newLine->type = $type; + $newLine->oldlc = $type != 'new' ? $oldCurrentLine : ''; + $newLine->newlc = $type != 'old' ? $newCurrentLine : ''; + $newLine->line = htmlSpecialString($line); + + if($type != 'new') $oldCurrentLine++; + if($type != 'old') $newCurrentLine++; + + $newLines[] = $newLine; + } + + $diff->lines = $newLines; + $diffFile->contents[] = $diff; + } + + if(isset($lines[$i]) and strpos($lines[$i], "diff --git ") === 0) + { + $i --; + $newFile = false; + break; + } + } + $diffs[] = $diffFile; + } + } + return $diffs; + } + + /** + * Get commit count. + * + * @param int $commits + * @param string $lastVersion + * @access public + * @return int + */ + public function getCommitCount($commits = 0, $lastVersion = '') + { + if(!scm::checkRevision($lastVersion)) return false; + + chdir($this->root); + $revision = $this->branch ? $this->branch : 'HEAD'; + return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string'); + } + + /** + * Get first revision. + * + * @access public + * @return string + */ + public function getFirstRevision() + { + chdir($this->root); + $list = execCmd(escapeCmd("$this->client rev-list --reverse HEAD -- ./"), 'array'); + return $list[0]; + } + + /** + * Get latest revision + * + * @access public + * @return string + */ + public function getLatestRevision() + { + chdir($this->root); + $revision = $this->branch ? $this->branch : 'HEAD'; + $list = execCmd(escapeCmd("$this->client rev-list -1 $revision -- ./"), 'array'); + return $list[0]; + } + + /** + * Get commits. + * + * @param string $rversion + * @param int $count + * @param string $branch + * @access public + * @return array + */ + public function getCommits($revision = '', $count = 0, $branch = '') + { + if(!scm::checkRevision($revision)) return array(); + + if($revision == 'HEAD' and $branch) $revision = $branch; + $count = $count == 0 ? '' : "-n $count"; + + chdir($this->root); + if($branch) + { + execCmd(escapeCmd("$this->client checkout $branch")); + execCmd(escapeCmd("$this->client pull")); + } + + $list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array'); + $commits = $this->parseLog($list); + + $logs = array(); + foreach($commits as $commit) + { + $hash = $commit->revision; + $log = new stdClass(); + $log->committer = $commit->committer; + $log->revision = $commit->revision; + $log->comment = $commit->comment; + $log->time = $commit->time; + $logs['commits'][$hash] = $log; + $logs['files'][$hash] = array(); + } + if(empty($logs)) return $logs; + + $hash = ''; + $files = execCmd(escapeCmd("$this->client whatchanged $count $revision --pretty=format:%an@_@%cd@_@%H@_@%s -- ./"), 'array'); + foreach($files as $commit) + { + $commit = trim($commit); + if(empty($commit)) continue; + $parsedCommit = explode('@_@', $commit); + if(count($parsedCommit) == 4) + { + list($account, $date, $hash, $comment) = $parsedCommit; + } + else + { + $file = explode(' ', $commit); + $file = 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; + } + } + return $logs; + } + + /** + * Get clone url. + * + * @access public + * @return string + */ + public function getCloneUrl() + { + $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; + } + + /** + * Parse log. + * + * @param array $logs + * @access public + * @return array + */ + public function parseLog($logs) + { + $parsedLogs = array(); + $i = 0; + foreach($logs as $line) + { + if(strpos($line, 'commit ') === 0) + { + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; + $i++; + } + + $log = new stdclass(); + $comment = ''; + $changes = array(); + + $log->revision = trim(preg_replace('/^commit/', '', $line)); + } + elseif(strpos($line, 'Author:') === 0) + { + $account = preg_replace('/^Author:/', '', $line); + $log->committer = trim(preg_replace('/<[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+>/', '', $account)); + } + elseif(strpos($line, 'Date:') === 0) + { + $date = trim(preg_replace('/^Date:/', '', $line)); + $log->time = date('Y-m-d H:i:s', strtotime($date)); + } + elseif(preg_match('/^\s{2,}/', $line)) + { + $comment .= $line; + } + elseif(strpos($line, "\t") !== false) + { + list($action, $entry) = explode("\t", $line); + $entry = '/' . trim($entry); + $pathInfo = array(); + $pathInfo['action'] = $action; + $pathInfo['kind'] = 'file'; + $changes[$entry] = $pathInfo; + } + } + + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; + } + + return $parsedLogs; + } +} diff --git a/module/git/model.php b/module/git/model.php index 602afcea43..20d9bbfeb5 100644 --- a/module/git/model.php +++ b/module/git/model.php @@ -128,18 +128,24 @@ class gitModel extends model $branches = $this->repo->getBranches($repo); $commits = $repo->commits; - $gitlabAccountPairs = array(); + $accountPairs = array(); if($repo->SCM == 'Gitlab') { - $gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService); - $acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService); - foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); + $userList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService); + $acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService); + foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); } elseif($repo->SCM == 'Gitea') { - $gitlabUserList = $this->loadModel('gitea')->apiGetUsers($repo->gitService); - $acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account'); - foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); + $userList = $this->loadModel('gitea')->apiGetUsers($repo->gitService); + $acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account'); + foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); + } + elseif($repo->SCM == 'Gogs') + { + $userList = $this->loadModel('gogs')->apiGetUsers($repo->gitService); + $acountIDPairs = $this->gogs->getUserAccountIdPairs($repo->gitService, 'openID,account'); + foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); } /* Update code commit history. */ @@ -180,7 +186,7 @@ class gitModel extends model ' task:' . join(' ', $objects['tasks']) . ' bug:' . join(',', $objects['bugs'])); - $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $gitlabAccountPairs); + $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $accountPairs); } else { diff --git a/module/gogs/model.php b/module/gogs/model.php index 0034530825..981fb10fbc 100644 --- a/module/gogs/model.php +++ b/module/gogs/model.php @@ -12,14 +12,6 @@ class gogsModel extends model { - - const HOOK_PUSH_EVENT = 'Push Hook'; - - /* Gitlab access level. */ - public $noAccess = 0; - public $developerAccess = 30; - public $maintainerAccess = 40; - /** * Get a gogs by id. * @@ -62,23 +54,15 @@ class gogsModel extends model * Get gogs api base url by gogs id. * * @param int $gogsID - * @param bool $sudo * @access public * @return string */ - public function getApiRoot($gogsID, $sudo = true) + public function getApiRoot($gogsID) { $gogs = $this->getByID($gogsID); if(!$gogs) return ''; - $sudoParam = ''; - if($sudo == true and !$this->app->user->admin) - { - $openID = $this->getUserIDByZentaoAccount($gogsID, $this->app->user->account); - if($openID) $sudoParam = "&sudo={$openID}"; - } - - return rtrim($gogs->url, '/') . '/api/v1%s' . "?token={$gogs->token}" . $sudoParam; + return rtrim($gogs->url, '/') . '/api/v1%s' . "?token={$gogs->token}"; } /** @@ -207,45 +191,6 @@ class gogsModel extends model return false; } - /** - * Check user access. - * - * @param int $gogsID - * @param int $projectID - * @param object $project - * @param string $maxRole - * @access public - * @return bool - */ - public function checkUserAccess($gogsID, $projectID = 0, $project = null, $groupIDList = array(), $maxRole = 'maintainer') - { - if($this->app->user->admin) return true; - - if($project == null) $project = $this->apiGetSingleProject($gogsID, $projectID); - if(!isset($project->id)) return false; - - $accessLevel = $this->config->gogs->accessLevel[$maxRole]; - - if(isset($project->permissions->project_access->access_level) and $project->permissions->project_access->access_level >= $accessLevel) return true; - if(isset($project->permissions->group_access->access_level) and $project->permissions->group_access->access_level >= $accessLevel) return true; - if(!empty($project->shared_with_groups)) - { - if(empty($groupIDList)) - { - $groups = $this->apiGetGroups($gogsID, 'name_asc', $maxRole); - foreach($groups as $group) $groupIDList[] = $group->id; - } - - foreach($project->shared_with_groups as $group) - { - if($group->group_access_level < $accessLevel) continue; - if(in_array($group->group_id, $groupIDList)) return true; - } - } - - return false; - } - /** * Check token access. * @@ -397,28 +342,48 @@ class gogsModel extends model * Get projects by api. * * @param int $gogsID - * @param bool $sudo * @access public * @return array */ - public function apiGetProjects($gogsID, $sudo = true) + public function apiGetProjects($gogsID) { - $apiRoot = $this->getApiRoot($gogsID, $sudo); + $apiRoot = $this->getApiRoot($gogsID); if(!$apiRoot) return array(); - $url = sprintf($apiRoot, "/repos/search"); + $user = $this->apiGetAdminer($gogsID); + if(!$user) return array(); + + $url = sprintf($apiRoot, "/users/{$user->username}/repos"); $allResults = array(); for($page = 1; true; $page++) { $results = json_decode(commonModel::http($url . "&page={$page}&limit=50")); - if(!is_array($results->data)) break; - if(!empty($results->data)) $allResults = array_merge($allResults, $results->data); - if(count($results->data) < 50) break; + if(!is_array($results)) break; + if(!empty($results)) $allResults = array_merge($allResults, $results); + if(count($results) < 50) break; } return $allResults; } + /** + * Api get adminer. + * + * @param int $gogsID + * @access public + * @return void + */ + public function apiGetAdminer($gogsID) + { + $apiRoot = $this->getApiRoot($gogsID); + if(!$apiRoot) return array(); + + $url = sprintf($apiRoot, "/user"); + $user = json_decode(commonModel::http($url)); + + return isset($user->username) ? $user : null; + } + /** * Get gogs user list. * @@ -491,31 +456,17 @@ class gogsModel extends model return $allResults; } - /** - * Get Forks of a project by API. - * - * @param int $gogsID - * @param string $projectID - * @access public - * @return object - */ - public function apiGetForks($gogsID, $projectID) - { - $url = sprintf($this->getApiRoot($gogsID), "/repos/$projectID/forks"); - return json_decode(commonModel::http($url)); - } - /** * Get upstream project by API. * - * @param int $gogsID - * @param string $projectID + * @param int $gogID + * @param string $project * @access public * @return void */ - public function apiGetUpstream($gogsID, $projectID) + public function apiGetUpstream($gogsID, $project) { - $currentProject = $this->apiGetSingleProject($gogsID, $projectID); + $currentProject = $this->apiGetSingleProject($gogsID, $project); if(isset($currentProject->parent->full_name)) return $currentProject->parent->full_name; return array(); } @@ -556,28 +507,6 @@ class gogsModel extends model ->fetchPairs(); } - /** - * Get single branch by API. - * - * @param int $gogsID - * @param string $project - * @param string $branchName - * @access public - * @return object - */ - public function apiGetSingleBranch($gogsID, $project, $branchName) - { - $url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branchName"); - $branch = json_decode(commonModel::http($url)); - if($branch) - { - $gogs = $this->getByID($gogsID); - $branch->web_url = "{$gogs->url}/$project/src/branch/$branchName"; - } - - return $branch; - } - /** * Get protect branches of one project. * @@ -589,19 +518,6 @@ class gogsModel extends model */ public function apiGetBranchPrivs($gogsID, $project, $keyword = '') { - $keyword = urlencode($keyword); - $url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branch_protections"); - $branches = json_decode(commonModel::http($url)); - - if(!is_array($branches)) return $branches; - - $newBranches = array(); - foreach($branches as $branch) - { - $branch->name = $branch->branch_name; - if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[] = $branch; - } - - return $newBranches; + return array(); } } diff --git a/module/mr/config.php b/module/mr/config.php index 3ffe3fd9bd..b0cb590a0b 100644 --- a/module/mr/config.php +++ b/module/mr/config.php @@ -33,4 +33,4 @@ $config->mrapproval->create = new stdclass(); $config->mrapproval->create->skippedFields = ''; $config->mrapproval->create->requiredFields = 'mrID,account,date,action'; -$config->mr->gitServiceList = array('gitlab', 'gitea'); +$config->mr->gitServiceList = array('gitlab', 'gitea', 'gogs'); diff --git a/module/mr/control.php b/module/mr/control.php index ad54afbbf9..1c1924bcea 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -109,21 +109,29 @@ class mr extends control $repo = $this->repo->getRepoByID($repoID); $this->loadModel('gitea'); + $this->loadModel('gogs'); if($repo->SCM == 'Gitea') { $project = $this->gitea->apiGetSingleProject($repo->gitService, $repo->project); if(empty($project) or !$project->allow_merge_commits) $repo = array(); } + elseif($repo->SCM == 'Gogs') + { + $project = $this->gitea->apiGetSingleProject($repo->gitService, $repo->project); + if(empty($project)) $repo = array(); + } - $hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab')); + $hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab', 'gogs')); if(!$this->app->user->admin) { $gitlabUsers = $this->loadModel('gitlab')->getGitLabListByAccount(); $giteaUsers = $this->gitea->getGiteaListByAccount(); + $gogsUsers = $this->gogs->getGiteaListByAccount(); foreach($hosts as $hostID => $host) { if($host->type == 'gitLab' and isset($gitlabUsers[$hostID])) continue; if($host->type == 'gitea' and isset($giteaUsers[$hostID])) continue; + if($host->type == 'gogs' and isset($gogsUsers[$hostID])) continue; unset($hosts[$hostID]); } diff --git a/module/mr/js/create.js b/module/mr/js/create.js index 316ecb0368..5c237ca2f6 100644 --- a/module/mr/js/create.js +++ b/module/mr/js/create.js @@ -156,10 +156,14 @@ $(function() { var url = createLink('repo', 'ajaxGetGitlabProjects', "gitlabID=" + hostID + "&projectIdList=&filter=IS_DEVELOPER"); } - else + else if(hosts[hostID].type == 'gitea') { var url = createLink('repo', 'ajaxGetGiteaProjects', "giteaID=" + hostID); } + else if(hosts[hostID].type == 'gogs') + { + var url = createLink('repo', 'ajaxGetGogsProjects', "gogsID=" + hostID); + } $.get(url, function(response) { if(response == "" && confirm(mrLang.addForApp) == true) window.open(hosts[hostID].url); diff --git a/module/mr/model.php b/module/mr/model.php index e85a33f5a6..4b1e294035 100644 --- a/module/mr/model.php +++ b/module/mr/model.php @@ -126,6 +126,19 @@ class mrModel extends model return array($hostID => array_column($projects, null, 'full_name')); } + /** + * Get gogs projects. + * + * @param int $hostID + * @access public + * @return array + */ + public function getGogsProjects($hostID = 0) + { + $projects = $this->loadModel('gogs')->apiGetProjects($hostID); + return array($hostID => array_column($projects, null, 'full_name')); + } + /** * Get gitlab projects. * @@ -657,7 +670,7 @@ class mrModel extends model } return json_decode(commonModel::http($url, $MRObject)); } - else + elseif($host->type == 'gitea') { $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls"); @@ -681,6 +694,14 @@ class mrModel extends model if(isset($mergeResult->merged) and $mergeResult->merged) $mergeResult->state = 'merged'; return $mergeResult; } + elseif($host->type == 'gogs') + { + $mergeResult = new stdClass(); + $mergeResult->iid = 0; + $mergeResult->merge_status = 'can_be_merged'; + $mergeResult->state = 'opened'; + return $mergeResult; + } } /** diff --git a/module/repo/config.php b/module/repo/config.php index 13855f8028..c4b6af2dc6 100644 --- a/module/repo/config.php +++ b/module/repo/config.php @@ -52,7 +52,8 @@ $config->repo->gitlab->apiPath = "%s/api/v4/projects/%s/repository/"; $config->repo->gitea = new stdclass; $config->repo->gitea->apiPath = "%s/api/v1/repos/%s/"; -$config->repo->gitServiceList = array('gitlab', 'gitea'); +$config->repo->gitServiceList = array('gitlab', 'gitea', 'gogs'); +$config->repo->gitTypeList = array('Gitlab', 'Gitea', 'Gogs', 'Git'); $config->repo->rules['module']['task'] = 'Task'; $config->repo->rules['module']['bug'] = 'Bug'; diff --git a/module/repo/control.php b/module/repo/control.php index 84bd9ba78a..5d178c0c46 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -192,6 +192,7 @@ class repo extends control { if($scm == 'gitlab') $options[$project->id] = $project->name_with_namespace; if($scm == 'gitea') $options[$project->full_name] = $project->full_name; + if($scm == 'gogs') $options[$project->full_name] = $project->full_name; } $this->view->projects = $options; @@ -308,13 +309,13 @@ class repo extends control foreach($revisions as $log) { if($revision == 'HEAD' and $i == 0) $revision = $log->revision; - if($revision == $log->revision) $revisionName = strpos($repo->SCM, 'Git') !== false ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision; + if($revision == $log->revision) $revisionName = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision; $i++; } if(!isset($revisionName)) { - if(strpos($repo->SCM, 'Git') !== false) $gitCommit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch('commit'); - $revisionName = (strpos($repo->SCM, 'Git') !== false and isset($gitCommit)) ? $this->repo->getGitRevisionName($revision, $gitCommit) : $revision; + if(in_array($repo->SCM, $this->config->repo->gitTypeList)) $gitCommit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch('commit'); + $revisionName = (in_array($repo->SCM, $this->config->repo->gitTypeList) and isset($gitCommit)) ? $this->repo->getGitRevisionName($revision, $gitCommit) : $revision; } $this->view->revisions = $revisions; @@ -386,7 +387,7 @@ class repo extends control /* Set branch or tag for git. */ $branches = $tags = $branchesAndTags = array(); - if(strpos($repo->SCM, 'Git') !== false) + if(in_array($repo->SCM, $this->config->repo->gitTypeList)) { $scm = $this->app->loadClass('scm'); $scm->setEngine($repo); @@ -436,7 +437,7 @@ class repo extends control /* Update code commit history. */ $commentGroup = $this->loadModel('job')->getTriggerGroup('commit', array($repo->id)); - if($refresh and strpos($repo->SCM, 'Git') !== false) + if($refresh and in_array($repo->SCM, $this->config->repo->gitTypeList)) { $branch = $this->cookie->repoBranch; $this->loadModel('git')->updateCommit($repo, $commentGroup, false); @@ -479,7 +480,7 @@ class repo extends control $revisions = $this->repo->getCommits($repo, $path, $revision, $logType, $pager); /* Synchronous commit only in root path. */ - if(strpos($repo->SCM, 'Git') !== false and empty($path) and $infos and empty($revisions)) $this->locate($this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID&branch=" . base64_encode($this->cookie->repoBranch))); + 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=" . base64_encode($this->cookie->repoBranch))); $this->view->title = $this->lang->repo->common; $this->view->repo = $repo; @@ -590,7 +591,7 @@ class repo extends control $history = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($log[0]->revision)->andWhere('repo')->eq($repoID)->fetch(); if($history) { - if(strpos($repo->SCM, 'Git') !== false) + if(in_array($repo->SCM, $this->config->repo->gitTypeList)) { $thisAndPrevRevisions = $this->scm->exec("rev-list -n 2 {$history->revision} --"); @@ -608,7 +609,7 @@ class repo extends control if(empty($oldRevision)) { $oldRevision = '^'; - if($history and strpos($repo->SCM, 'Git') !== false) $oldRevision = "{$history->revision}^"; + if($history and in_array($repo->SCM, $this->config->repo->gitTypeList)) $oldRevision = "{$history->revision}^"; } $changes = array(); @@ -694,7 +695,7 @@ class repo extends control if($encoding != 'utf-8') $blames[$i]['content'] = helper::convertEncoding($blame['content'], $encoding); } - $log = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch() : ''; + $log = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch() : ''; $this->view->title = $this->lang->repo->common; $this->view->repoID = $repoID; @@ -705,8 +706,8 @@ class repo extends control $this->view->entry = $entry; $this->view->file = $file; $this->view->encoding = str_replace('-', '_', $encoding); - $this->view->historys = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($revisions)->andWhere('repo')->eq($repo->id)->fetchPairs() : ''; - $this->view->revisionName = ($log and strpos($repo->SCM, 'Git') !== false) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $revision; + $this->view->historys = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($revisions)->andWhere('repo')->eq($repo->id)->fetchPairs() : ''; + $this->view->revisionName = ($log and in_array($repo->SCM, $this->config->repo->gitTypeList)) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $revision; $this->view->blames = $blames; $this->display(); } @@ -822,7 +823,7 @@ class repo extends control $this->view->newRevision = $newRevision; $this->view->oldRevision = $oldRevision; $this->view->revision = $newRevision; - $this->view->historys = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in("$oldRevision,$newRevision")->andWhere('repo')->eq($repo->id)->fetchPairs() : ''; + $this->view->historys = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in("$oldRevision,$newRevision")->andWhere('repo')->eq($repo->id)->fetchPairs() : ''; $this->view->info = $info; $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->diff; @@ -942,7 +943,7 @@ class repo extends control $this->scm->setEngine($repo); $branchID = ''; - if(strpos($repo->SCM, 'Git') !== false and empty($branchID)) + if(in_array($repo->SCM, $this->config->repo->gitTypeList) and empty($branchID)) { $branches = $this->scm->branch(); if($branches) @@ -979,7 +980,7 @@ class repo extends control $version = empty($latestInDB) ? 1 : $latestInDB->commit + 1; $logs = array(); - $revision = $version == 1 ? 'HEAD' : ($repo->SCM == 'Git' ? $latestInDB->commit : $latestInDB->revision); + $revision = $version == 1 ? 'HEAD' : (in_array($repo->SCM, array('Git', 'Gitea', 'Gogs')) ? $latestInDB->commit : $latestInDB->revision); if($type == 'batch') { $logs = $this->scm->getCommits($revision, $this->config->repo->batchNum, $branchID); @@ -994,7 +995,7 @@ class repo extends control { if(!$repo->synced) { - if(strpos($repo->SCM, 'Git') !== false) + if(in_array($repo->SCM, $this->config->repo->gitTypeList)) { if($branchID) $this->repo->saveExistCommits4Branch($repo->id, $branchID); @@ -1029,7 +1030,7 @@ class repo extends control set_time_limit(0); $repo = $this->repo->getRepoByID($repoID); if(empty($repo)) return; - if(strpos($repo->SCM, 'Git') === false) return print('finish'); + if(!in_array($repo->SCM, $this->config->repo->gitTypeList)) return print('finish'); if($branch) $branch = base64_decode($branch); $this->scm->setEngine($repo); @@ -1040,7 +1041,7 @@ class repo extends control $latestInDB = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1') ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') ->where('t1.repo')->eq($repoID) - ->beginIF(strpos($repo->SCM, 'Git') !== false and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() + ->beginIF(in_array($repo->SCM, $this->config->repo->gitTypeList) and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() ->orderBy('t1.time') ->limit(1) ->fetch(); @@ -1198,8 +1199,8 @@ class repo extends control /** * Ajax get gitea projects. * - * @param string $gitlabID - * @param string $projectIdList + * @param string $gitlabID + * @param string $projectIdList * @access public * @return void */ @@ -1214,11 +1215,30 @@ class repo extends control return print($options); } + /** + * Ajax get gogs projects. + * + * @param string $gitlabID + * @param string $projectIdList + * @access public + * @return void + */ + public function ajaxGetGogsProjects($gogsID) + { + $projects = $this->loadModel('gogs')->apiGetProjects($gogsID); + if(!$projects) $this->send(array('message' => array())); + + $options = ""; + foreach($projects as $project) $options .= ""; + + return print($options); + } + /** * Ajax get gitlab projects. * - * @param string $gitlabID - * @param string $token + * @param string $gitlabID + * @param string $token * @access public * @return void */ @@ -1364,12 +1384,16 @@ class repo extends control } $repo = $this->repo->getRepoByID($repoID); - if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) + if($repo->SCM == 'Gitlab') { $this->scm = $this->app->loadClass('scm'); $this->scm->setEngine($repo); $url = $this->scm->getDownloadUrl($branch); } + elseif(in_array($repo->SCM, array('Gitea', 'Gogs'))) + { + $url = "$repo->codePath/archive/{$branch}.zip"; + } elseif($repo->SCM == 'Git') { $gitDir = scandir($repo->path); diff --git a/module/repo/js/create.js b/module/repo/js/create.js index 296337d8e2..3d17fb25a6 100644 --- a/module/repo/js/create.js +++ b/module/repo/js/create.js @@ -54,7 +54,7 @@ $(function() */ function scmChanged(scm) { - if(scm == 'Git' || scm == 'Gitea') + if(scm == 'Git' || scm == 'Gitea' || scm == 'Gogs') { $('.account-fields').addClass('hidden'); @@ -76,11 +76,12 @@ function scmChanged(scm) } else { + $('.tips').addClass('hidden'); $('tr.service').toggle(true); - if(scm == 'Gitea') + if(scm == 'Gitea' || scm == 'Gogs') { - $('tr.hide-service:not(".hide-gitea")').toggle(true); - $('tr.hide-gitea').toggle(false); + $('tr.hide-service:not(".hide-git")').toggle(true); + $('tr.hide-git').toggle(false); } else { diff --git a/module/repo/js/edit.js b/module/repo/js/edit.js index 2c5510ca06..0a37664742 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' || scm == 'Gitea') + if(scm == 'Git' || scm == 'Gitea' || scm == 'Gogs') { $('.account-fields').addClass('hidden'); @@ -60,11 +60,12 @@ function scmChanged(scm, isFirstRequest = false) } else { + $('.tips').addClass('hidden'); $('tr.service').toggle(true); - if(scm == 'Gitea') + if(scm == 'Gitea' || scm == 'Gogs') { - $('tr.hide-service:not(".hide-gitea")').toggle(true); - $('tr.hide-gitea').toggle(false); + $('tr.hide-service:not(".hide-git")').toggle(true); + $('tr.hide-git').toggle(false); } else { diff --git a/module/repo/lang/de.php b/module/repo/lang/de.php index 54c8aad4ea..eef3df7db5 100644 --- a/module/repo/lang/de.php +++ b/module/repo/lang/de.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gogs'] = 'Gogs'; $lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; diff --git a/module/repo/lang/en.php b/module/repo/lang/en.php index 5d9b5bbd87..025d4901ab 100644 --- a/module/repo/lang/en.php +++ b/module/repo/lang/en.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gogs'] = 'Gogs'; $lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; diff --git a/module/repo/lang/fr.php b/module/repo/lang/fr.php index ff2f8c8246..28e405a979 100644 --- a/module/repo/lang/fr.php +++ b/module/repo/lang/fr.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gogs'] = 'Gogs'; $lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'Subversion'; diff --git a/module/repo/lang/vi.php b/module/repo/lang/vi.php index 16eb83b534..aa05c51e62 100644 --- a/module/repo/lang/vi.php +++ b/module/repo/lang/vi.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gogs'] = 'Gogs'; $lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; diff --git a/module/repo/lang/zh-cn.php b/module/repo/lang/zh-cn.php index f94930c892..e791a70c1d 100644 --- a/module/repo/lang/zh-cn.php +++ b/module/repo/lang/zh-cn.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gogs'] = 'Gogs'; $lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = '本地 Git'; $lang->repo->scmList['Subversion'] = 'Subversion'; diff --git a/module/repo/model.php b/module/repo/model.php index 817276d1e8..fe8ff36ed2 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -436,17 +436,22 @@ class repoModel extends model $repo = str_replace('[gitlab]', '', $repo); $repos['Gitlab'][$id] = $repo; } - if(strpos($repo, '[gitea]') !== false) + elseif(strpos($repo, '[gogs]') !== false) + { + $repo = str_replace('[gogs]', '', $repo); + $repos['Gogs'][$id] = $repo; + } + elseif(strpos($repo, '[gitea]') !== false) { $repo = str_replace('[gitea]', '', $repo); $repos['Gitea'][$id] = $repo; } - if(strpos($repo, '[svn]') !== false) + elseif(strpos($repo, '[svn]') !== false) { $repo = str_replace('[svn]', '', $repo); $repos['SVN'][$id] = $repo; } - if(strpos($repo, '[git]') !== false) + elseif(strpos($repo, '[git]') !== false) { $repo = str_replace('[git]', '', $repo); $repos['Git'][$id] = $repo; @@ -1415,14 +1420,15 @@ class repoModel extends model return false; } } - elseif($scm == 'Gitea') + elseif(in_array($scm, array('Gitea', 'Gogs'))) { if($this->post->name != '' and $this->post->serviceProject != '') { - $project = $this->loadModel('gitea')->apiGetSingleProject($this->post->serviceHost, $this->post->serviceProject); + $module = strtolower($scm); + $project = $this->loadModel($module)->apiGetSingleProject($this->post->serviceHost, $this->post->serviceProject); if(isset($project->tokenCloneUrl)) { - $path = dirname(dirname(dirname(__FILE__))) . '/tmp/repo/' . $this->post->name . '_gitea'; + $path = $this->app->getAppRoot() . 'www/data/repo/' . $this->post->name . '_' . $module; if(!realpath($path)) { $cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $path . '"'; @@ -2073,7 +2079,7 @@ class repoModel extends model $repo->password = $service ? $service->token : ''; $repo->codePath = $project ? $project->web_url : $repo->path; } - elseif($repo->SCM == 'Gitea') + elseif(in_array($repo->SCM, array('Gitea', 'Gogs'))) { $repo->codePath = $service ? "{$service->url}/{$repo->serviceProject}" : $repo->path; } @@ -2214,6 +2220,15 @@ class repoModel extends model $url->ssh = $project->ssh_url; } } + elseif($repo->SCM == 'Gogs') + { + $project = $this->loadModel('gogs')->apiGetSingleProject($repo->gitService, $repo->project); + if(isset($project->id)) + { + $url->http = $project->clone_url; + $url->ssh = $project->ssh_url; + } + } else { $this->scm = $this->app->loadClass('scm'); diff --git a/module/repo/view/create.html.php b/module/repo/view/create.html.php index 298d1b935f..74c07cc819 100644 --- a/module/repo/view/create.html.php +++ b/module/repo/view/create.html.php @@ -30,7 +30,7 @@ repo->type; ?> repo->scmList, 'Gitlab', "onchange='scmChanged(this.value)' class='form-control chosen'"); ?> - repo->syncTips; ?> + repo->syncTips; ?> repo->serviceHost;?> @@ -45,7 +45,7 @@ - + repo->path; ?> diff --git a/module/repo/view/edit.html.php b/module/repo/view/edit.html.php index c19a57b702..485b4317d1 100644 --- a/module/repo/view/edit.html.php +++ b/module/repo/view/edit.html.php @@ -34,7 +34,7 @@ repo->type; ?> repo->scmList, $repo->SCM, "onchange='scmChanged(this.value)' class='form-control chosen'"); ?> - repo->syncTips; ?> + repo->syncTips; ?> repo->serviceHost;?> @@ -49,7 +49,7 @@ name, "class='form-control'"); ?> - + repo->path; ?> path, "class='form-control'"); ?> diff --git a/module/repo/view/maintain.html.php b/module/repo/view/maintain.html.php index 7dfebcc968..b8aee00e0f 100644 --- a/module/repo/view/maintain.html.php +++ b/module/repo/view/maintain.html.php @@ -30,7 +30,7 @@ repo->name); ?> repo->product); ?> repo->path; ?> - actions; ?> + actions; ?> diff --git a/module/upgrade/config.php b/module/upgrade/config.php index 9b79b1efbd..e9c35afe3e 100644 --- a/module/upgrade/config.php +++ b/module/upgrade/config.php @@ -367,6 +367,6 @@ $config->delete['17_2'][] = 'extension/lite/workflowrelation/ext/view/admin.flow $config->delete['17_2'][] = 'extension/lite/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php'; $config->delete['17_2'][] = 'extension/lite/extension/lite/workflowrule/ext/view/view.flow.html.hook.php'; -$config->upgrade->openModules = array('action', 'admin', 'api', 'automation', 'backup', 'block', 'branch', 'budget', 'bug', 'build', 'caselib', 'ci', 'client', 'common', 'company', 'compile', 'convert', 'cron', 'custom', 'datatable', 'dept', 'design', 'dev', 'doc', 'durationestimation', 'entry', 'execution', 'extension', 'file', 'git', 'gitlab', 'group', 'holiday', 'im', 'index', 'index.html', 'install', 'issue', 'jenkins', 'job', 'kanban', 'license', 'mail', 'message', 'misc', 'mr', 'my', 'personnel', 'pipeline', 'product', 'productplan', 'productset', 'program', 'programplan', 'project', 'projectbuild', 'projectrelease', 'projectstory', 'qa', 'release', 'repo', 'report', 'risk', 'score', 'search', 'setting', 'sonarqube', 'sso', 'stage', 'stakeholder', 'story', 'subject', 'svn', 'task', 'testcase', 'testreport', 'testsuite', 'testtask', 'todo', 'tree', 'tutorial', 'upgrade', 'user', 'webhook', 'weekly', 'workestimation', 'gitea'); +$config->upgrade->openModules = array('action', 'admin', 'api', 'automation', 'backup', 'block', 'branch', 'budget', 'bug', 'build', 'caselib', 'ci', 'client', 'common', 'company', 'compile', 'convert', 'cron', 'custom', 'datatable', 'dept', 'design', 'dev', 'doc', 'durationestimation', 'entry', 'execution', 'extension', 'file', 'git', 'gitlab', 'group', 'holiday', 'im', 'index', 'index.html', 'install', 'issue', 'jenkins', 'job', 'kanban', 'license', 'mail', 'message', 'misc', 'mr', 'my', 'personnel', 'pipeline', 'product', 'productplan', 'productset', 'program', 'programplan', 'project', 'projectbuild', 'projectrelease', 'projectstory', 'qa', 'release', 'repo', 'report', 'risk', 'score', 'search', 'setting', 'sonarqube', 'sso', 'stage', 'stakeholder', 'story', 'subject', 'svn', 'task', 'testcase', 'testreport', 'testsuite', 'testtask', 'todo', 'tree', 'tutorial', 'upgrade', 'user', 'webhook', 'weekly', 'workestimation', 'gitea', 'gogs'); -$config->upgrade->unsetModules = array('design', 'program', 'programplan', 'projectbuild', 'projectrelease', 'stage', 'stakeholder', 'product', 'branch', 'productplan', 'release', 'build', 'qa', 'bug', 'testcase', 'testtask', 'testreport', 'testsuite', 'caselib', 'automation', 'repo', 'ci', 'compile', 'jenkins', 'job', 'svn', 'gitlab', 'sonarqube', 'mr', 'git', 'report', 'sqlbuilder', 'feedback', 'faq', 'attend', 'holiday', 'leave', 'makeup', 'overtime', 'lieu', 'ops', 'host', 'serverroom', 'account', 'domain', 'service', 'deploy', 'conference', 'traincourse', 'pssp', 'baseline', 'classify', 'cm', 'cmcl', 'auditcl', 'reviewcl', 'process', 'activity', 'zoutput', 'auditplan', 'nc', 'subject', 'weekly', 'workestimation', 'issue', 'durationestimation', 'risk', 'opportunity', 'trainplan', 'gapanalysis', 'researchplan', 'researchreport', 'meeting', 'meetingroom', 'budget', 'reviewissue', 'reviewsetting', 'review', 'milestone', 'measurement', 'measrecord', 'assetlib', 'setting', 'im', 'client', 'ldap', 'dev', 'api', 'gitea'); +$config->upgrade->unsetModules = array('design', 'program', 'programplan', 'projectbuild', 'projectrelease', 'stage', 'stakeholder', 'product', 'branch', 'productplan', 'release', 'build', 'qa', 'bug', 'testcase', 'testtask', 'testreport', 'testsuite', 'caselib', 'automation', 'repo', 'ci', 'compile', 'jenkins', 'job', 'svn', 'gitlab', 'sonarqube', 'mr', 'git', 'report', 'sqlbuilder', 'feedback', 'faq', 'attend', 'holiday', 'leave', 'makeup', 'overtime', 'lieu', 'ops', 'host', 'serverroom', 'account', 'domain', 'service', 'deploy', 'conference', 'traincourse', 'pssp', 'baseline', 'classify', 'cm', 'cmcl', 'auditcl', 'reviewcl', 'process', 'activity', 'zoutput', 'auditplan', 'nc', 'subject', 'weekly', 'workestimation', 'issue', 'durationestimation', 'risk', 'opportunity', 'trainplan', 'gapanalysis', 'researchplan', 'researchreport', 'meeting', 'meetingroom', 'budget', 'reviewissue', 'reviewsetting', 'review', 'milestone', 'measurement', 'measrecord', 'assetlib', 'setting', 'im', 'client', 'ldap', 'dev', 'api', 'gitea', 'gogs'); From 5559558e40e6c7ad986c854f316c264a93476b2c Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 16:11:30 +0800 Subject: [PATCH 004/106] * Modify file download. --- module/repo/control.php | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/module/repo/control.php b/module/repo/control.php index 5d178c0c46..263aa3db46 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -1390,26 +1390,12 @@ class repo extends control $this->scm->setEngine($repo); $url = $this->scm->getDownloadUrl($branch); } - elseif(in_array($repo->SCM, array('Gitea', 'Gogs'))) + elseif($repo->SCM == 'Gitea') { - $url = "$repo->codePath/archive/{$branch}.zip"; + $api = $this->loadModel('gitea')->getApiRoot($repo->serviceHost); + $url = sprintf($api, "/repos/{$repo->serviceProject}/archive/{$branch}.zip"); } - elseif($repo->SCM == 'Git') - { - $gitDir = scandir($repo->path); - $files = ''; - foreach($gitDir as $path) - { - if(!in_array($path, array('.', '..', '.git'))) $files .= $repo->path . DS . "$path,"; - } - - $this->app->loadClass('pclzip', true); - $zip = new pclzip($fileName); - if($zip->create($files, PCLZIP_OPT_REMOVE_PATH, $repo->path) === 0) return print(js::alert($zip->errorInfo()) . js::close()); - - $url = $this->config->webRoot . $this->app->getAppName() . 'data' . DS . 'repo' . DS . $repo->name . '.zip'; - } - else + elseif($repo->SCM == 'Subversion') { /* Checkout repo. */ chdir($savePath); @@ -1427,6 +1413,21 @@ class repo extends control $url = $this->config->webRoot . $this->app->getAppName() . 'data' . DS . 'repo' . DS . $repo->name . '.zip'; } + else + { + $gitDir = scandir($repo->path); + $files = ''; + foreach($gitDir as $path) + { + if(!in_array($path, array('.', '..', '.git'))) $files .= $repo->path . DS . "$path,"; + } + + $this->app->loadClass('pclzip', true); + $zip = new pclzip($fileName); + if($zip->create($files, PCLZIP_OPT_REMOVE_PATH, $repo->path) === 0) return print(js::alert($zip->errorInfo()) . js::close()); + + $url = $this->config->webRoot . $this->app->getAppName() . 'data' . DS . 'repo' . DS . $repo->name . '.zip'; + } $this->locate($url); } From 988982d4a8944db4499f2aeb65782d8f9eac30fb Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 16:16:41 +0800 Subject: [PATCH 005/106] * Adjust code. --- module/gogs/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/gogs/model.php b/module/gogs/model.php index 981fb10fbc..243af570fd 100644 --- a/module/gogs/model.php +++ b/module/gogs/model.php @@ -459,7 +459,7 @@ class gogsModel extends model /** * Get upstream project by API. * - * @param int $gogID + * @param int $gogsID * @param string $project * @access public * @return void From eaf6fcdb446b5f56f17a67cd33c05f4460b93333 Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 16:21:05 +0800 Subject: [PATCH 006/106] * Adjust codes. --- module/gogs/model.php | 14 -------------- module/mr/control.php | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/module/gogs/model.php b/module/gogs/model.php index 243af570fd..04504e2458 100644 --- a/module/gogs/model.php +++ b/module/gogs/model.php @@ -506,18 +506,4 @@ class gogsModel extends model ->andWhere('providerID')->eq($gogsID) ->fetchPairs(); } - - /** - * Get protect branches of one project. - * - * @param int $gogsID - * @param string $project - * @param string $keyword - * @access public - * @return array - */ - public function apiGetBranchPrivs($gogsID, $project, $keyword = '') - { - return array(); - } } diff --git a/module/mr/control.php b/module/mr/control.php index 1c1924bcea..f94de61883 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -177,10 +177,13 @@ class mr extends control $branchList = $this->loadModel($scm)->getBranches($MR->hostID, $MR->targetProject); $MR->canDeleteBranch = true; - $branchPrivs = $this->loadModel($scm)->apiGetBranchPrivs($MR->hostID, $MR->sourceProject); - foreach($branchPrivs as $priv) + if($scm != 'gogs') { - if($MR->canDeleteBranch and $priv->name == $MR->sourceBranch) $MR->canDeleteBranch = false; + $branchPrivs = $this->loadModel($scm)->apiGetBranchPrivs($MR->hostID, $MR->sourceProject); + foreach($branchPrivs as $priv) + { + if($MR->canDeleteBranch and $priv->name == $MR->sourceBranch) $MR->canDeleteBranch = false; + } } $targetBranchList = array(); @@ -1061,9 +1064,13 @@ class mr extends control $scm = $host->type; if($scm == 'gitea') $project = urldecode(base64_decode($project)); - $branches = $this->loadModel($scm)->apiGetBranchPrivs($hostID, $project); $branchPrivs = array(); - foreach($branches as $branch) $branchPrivs[$branch->name] = $branch->name; + + if($scm != 'gogs') + { + $branches = $this->loadModel($scm)->apiGetBranchPrivs($hostID, $project); + foreach($branches as $branch) $branchPrivs[$branch->name] = $branch->name; + } echo json_encode($branchPrivs); } } From 7a9885309f0e620388491c37a1b05db273ccad28 Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 17:04:49 +0800 Subject: [PATCH 007/106] * Modify git clone url get. --- lib/scm/gitrepo.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scm/gitrepo.class.php b/lib/scm/gitrepo.class.php index 6bf5f0646a..a598f49a2a 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -603,7 +603,8 @@ class GitRepo { $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/'; + if(strpos($remote[0], 'oauth2:')) $remote[0] = preg_replace('/oauth2.*@/', '', $remote[0]); + $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]; From 8d1632bdcc9f68f49500b3284fa4e3aa7ad01d5b Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Mon, 1 Aug 2022 17:13:44 +0800 Subject: [PATCH 008/106] * Modify repo btn style. --- module/repo/view/maintain.html.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/module/repo/view/maintain.html.php b/module/repo/view/maintain.html.php index b8aee00e0f..2eb4888c64 100644 --- a/module/repo/view/maintain.html.php +++ b/module/repo/view/maintain.html.php @@ -13,7 +13,7 @@