From 0683dba9df0ca56253dba8fc45c1ec8759cd69c2 Mon Sep 17 00:00:00 2001 From: aaronchen2k <462826@qq.com> Date: Mon, 20 Jan 2020 12:27:42 +0800 Subject: [PATCH] split ci module to more than modules --- module/ci/config.php | 18 - module/ci/control.php | 612 ----------- module/ci/js/browsecitask.js | 4 - module/ci/lang/zh-cn.php | 165 +-- module/ci/model.php | 961 ------------------ module/ci/view/header.html.php | 3 +- module/ci/view/menu.html.php | 2 +- module/cicredentials/config.php | 3 + module/cicredentials/control.php | 119 +++ .../js/browse.js} | 0 .../js/create.js} | 0 .../js/edit.js} | 0 module/cicredentials/lang/en.php | 1 + module/cicredentials/lang/zh-cn.php | 21 + module/cicredentials/model.php | 106 ++ .../view/browse.html.php} | 33 +- .../view/create.html.php} | 25 +- .../view/edit.html.php} | 41 +- module/cijenkins/config.php | 3 + module/cijenkins/control.php | 124 +++ .../js/browse.js} | 0 .../js/create.js} | 0 .../editjenkins.js => cijenkins/js/edit.js} | 0 module/cijenkins/lang/en.php | 1 + module/cijenkins/lang/zh-cn.php | 21 + module/cijenkins/model.php | 107 ++ .../view/browse.html.php} | 13 +- .../view/create.html.php} | 9 +- .../view/edit.html.php} | 9 +- module/cirepo/config.php | 8 + module/cirepo/control.php | 303 ++++++ .../js/browserepo.js => cirepo/js/browse.js} | 0 module/{ci => cirepo}/js/browsebranch.js | 2 +- .../js/createrepo.js => cirepo/js/create.js} | 0 .../{ci/js/editrepo.js => cirepo/js/edit.js} | 0 module/cirepo/lang/en.php | 1 + module/cirepo/lang/zh-cn.php | 69 ++ module/cirepo/model.php | 456 +++++++++ .../view/browse.html.php} | 17 +- .../{ci => cirepo}/view/browsebranch.html.php | 15 +- .../view/create.html.php} | 9 +- .../view/edit.html.php} | 9 +- .../view/showsynccomment.html.php | 5 +- module/citask/config.php | 1 + module/citask/control.php | 165 +++ .../css/browse.css} | 0 .../css/create.css} | 0 .../editcitask.css => citask/css/edit.css} | 0 module/citask/js/browse.js | 4 + .../createcitask.js => citask/js/create.js} | 1 + .../js/editcitask.js => citask/js/edit.js} | 1 + module/citask/lang/en.php | 1 + module/citask/lang/zh-cn.php | 42 + module/citask/model.php | 345 +++++++ .../view/browse.html.php} | 19 +- .../view/create.html.php} | 5 +- .../view/edit.html.php} | 5 +- module/common/lang/zh-cn.php | 7 +- module/git/config.php | 3 + module/git/model.php | 2 +- www/js/my.full.js | 4 + 61 files changed, 2032 insertions(+), 1868 deletions(-) delete mode 100644 module/ci/js/browsecitask.js create mode 100644 module/cicredentials/config.php create mode 100644 module/cicredentials/control.php rename module/{ci/js/browsecredential.js => cicredentials/js/browse.js} (100%) rename module/{ci/js/createcredential.js => cicredentials/js/create.js} (100%) rename module/{ci/js/editcredential.js => cicredentials/js/edit.js} (100%) create mode 100644 module/cicredentials/lang/en.php create mode 100644 module/cicredentials/lang/zh-cn.php create mode 100644 module/cicredentials/model.php rename module/{ci/view/browsecredential.html.php => cicredentials/view/browse.html.php} (62%) rename module/{ci/view/createcredential.html.php => cicredentials/view/create.html.php} (77%) rename module/{ci/view/editcredential.html.php => cicredentials/view/edit.html.php} (65%) create mode 100644 module/cijenkins/config.php create mode 100644 module/cijenkins/control.php rename module/{ci/js/browsejenkins.js => cijenkins/js/browse.js} (100%) rename module/{ci/js/createjenkins.js => cijenkins/js/create.js} (100%) rename module/{ci/js/editjenkins.js => cijenkins/js/edit.js} (100%) create mode 100644 module/cijenkins/lang/en.php create mode 100644 module/cijenkins/lang/zh-cn.php create mode 100644 module/cijenkins/model.php rename module/{ci/view/browsejenkins.html.php => cijenkins/view/browse.html.php} (87%) rename module/{ci/view/createjenkins.html.php => cijenkins/view/create.html.php} (90%) rename module/{ci/view/editjenkins.html.php => cijenkins/view/edit.html.php} (89%) create mode 100644 module/cirepo/config.php create mode 100644 module/cirepo/control.php rename module/{ci/js/browserepo.js => cirepo/js/browse.js} (100%) rename module/{ci => cirepo}/js/browsebranch.js (74%) rename module/{ci/js/createrepo.js => cirepo/js/create.js} (100%) rename module/{ci/js/editrepo.js => cirepo/js/edit.js} (100%) create mode 100644 module/cirepo/lang/en.php create mode 100644 module/cirepo/lang/zh-cn.php create mode 100644 module/cirepo/model.php rename module/{ci/view/browserepo.html.php => cirepo/view/browse.html.php} (84%) rename module/{ci => cirepo}/view/browsebranch.html.php (73%) rename module/{ci/view/createrepo.html.php => cirepo/view/create.html.php} (93%) rename module/{ci/view/editrepo.html.php => cirepo/view/edit.html.php} (93%) rename module/{ci => cirepo}/view/showsynccomment.html.php (84%) create mode 100644 module/citask/config.php create mode 100644 module/citask/control.php rename module/{ci/css/browsecitask.css => citask/css/browse.css} (100%) rename module/{ci/css/createcitask.css => citask/css/create.css} (100%) rename module/{ci/css/editcitask.css => citask/css/edit.css} (100%) create mode 100644 module/citask/js/browse.js rename module/{ci/js/createcitask.js => citask/js/create.js} (95%) rename module/{ci/js/editcitask.js => citask/js/edit.js} (96%) create mode 100644 module/citask/lang/en.php create mode 100644 module/citask/lang/zh-cn.php create mode 100644 module/citask/model.php rename module/{ci/view/browsecitask.html.php => citask/view/browse.html.php} (84%) rename module/{ci/view/createcitask.html.php => citask/view/create.html.php} (97%) rename module/{ci/view/editcitask.html.php => citask/view/edit.html.php} (97%) diff --git a/module/ci/config.php b/module/ci/config.php index ef1c6b446c..b3d9bbc7f3 100644 --- a/module/ci/config.php +++ b/module/ci/config.php @@ -1,19 +1 @@ credential->create->requiredFields = 'name,serviceUrl'; -$config->credential->edit->requiredFields = 'name,serviceUrl'; - -$config->jenkins->create->requiredFields = 'name'; -$config->jenkins->edit->requiredFields = 'name'; - -$config->repo->create->requiredFields = 'SCM,name,path,encoding,client,credential'; -$config->repo->edit->requiredFields = 'SCM,name,path,encoding,client,credential'; -$config->repo->cacheTime = 10; -$config->repo->syncTime = 10; -$config->repo->batchNum = 100; -$config->repo->images = '|png|gif|jpg|ico|jpeg|bmp|'; -$config->repo->binary = '|pdf|'; - -$config->repo->requiredFields = 'name,repo,buildType,jenkins,jenkinsTask,triggerType'; - -$config->ci->commitCommandRegx = '/\s*([a-z]+)\s+((?:build)|(?:story)|(?:task)|(?:bug))\s+#((?:\d|,)+)\s*/i'; -$config->ci->tagCommandRegx = '/build[\-_]#((?:\d|,)+)/i'; \ No newline at end of file diff --git a/module/ci/control.php b/module/ci/control.php index 213240f3f7..7d1a894389 100644 --- a/module/ci/control.php +++ b/module/ci/control.php @@ -20,7 +20,6 @@ class ci extends control public function __construct($moduleName = '', $methodName = '') { parent::__construct($moduleName, $methodName); - $this->scm = $this->app->loadClass('scm'); } /** @@ -34,615 +33,4 @@ class ci extends control $this->display(); } - /** - * Browse credentials - * - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - */ - public function browseCredential($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $this->view->title = $this->lang->credential->common . $this->lang->colon . $this->lang->ci->list; - $this->view->credentialList = $this->ci->listCredential($orderBy, $pager); - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = $this->lang->credential->common; - - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->module = 'credential'; - $this->display(); - } - - /** - * Create a credential. - * - * @access public - * @return void - */ - public function createCredential() - { - if($_POST) - { - $this->ci->createCredential(); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseCredential'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->credential->create . $this->lang->colon . $this->lang->credential->common; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseCredential'), $this->lang->credential->common); - $this->view->position[] = $this->lang->credential->create; - - $this->view->module = 'credential'; - $this->display(); - } - - /** - * Edit a credential. - * - * @param int $id - * @access public - * @return void - */ - public function editCredential($id) - { - $credential = $this->ci->getCredentialByID($id); - if($_POST) - { - $this->ci->updateCredential($id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseCredential'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->credential->edit . $this->lang->colon . $credential->name; - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseCredential'), $this->lang->credential->common); - $this->view->position[] = $this->lang->credential->edit; - - $this->view->credential = $credential; - - $this->view->module = 'credential'; - $this->display(); - } - - /** - * Delete a credential. - * - * @param int $id - * @access public - * @return void - */ - public function deleteCredential($id) - { - $this->ci->delete(TABLE_CREDENTIALS, $id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $this->send(array('result' => 'success')); - } - - /** - * Browse jenkinss. - * - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browseJenkins($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $this->view->title = $this->lang->jenkins->common . $this->lang->colon . $this->lang->ci->list; - $this->view->jenkinsList = $this->ci->listJenkins($orderBy, $pager); - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = $this->lang->jenkins->common; - - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->module = 'jenkins'; - $this->display(); - } - - /** - * Create a jenkins. - * - * @access public - * @return void - */ - public function createJenkins() - { - if($_POST) - { - $this->ci->createJenkins(); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseJenkins'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->jenkins->create . $this->lang->colon . $this->lang->jenkins->common; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseJenkins'), $this->lang->jenkins->common); - $this->view->position[] = $this->lang->jenkins->create; - - $this->view->credentialList = $this->ci->listCredentialForSelection("type='token' or type='account'"); - $this->view->module = 'jenkins'; - - $this->display(); - } - - /** - * Edit a jenkins. - * - * @param int $id - * @access public - * @return void - */ - public function editJenkins($id) - { - $jenkins = $this->ci->getJenkinsByID($id); - if($_POST) - { - $this->ci->updateJenkins($id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseJenkins'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->jenkins->edit . $this->lang->colon . $jenkins->name; - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseJenkins'), $this->lang->jenkins->common); - $this->view->position[] = $this->lang->jenkins->edit; - - $this->view->jenkins = $jenkins; - $this->view->credentialList = $this->ci->listCredentialForSelection("type='token' or type='account'"); - - $this->view->module = 'jenkins'; - $this->display(); - } - - /** - * Delete a jenkins. - * - * @param int $id - * @access public - * @return void - */ - public function deleteJenkins($id) - { - $this->ci->delete(TABLE_JENKINS, $id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $this->send(array('result' => 'success')); - } - - /** - * Browse ci task. - * - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browseCitask($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $this->view->title = $this->lang->citask->common . $this->lang->colon . $this->lang->ci->list; - $this->view->citaskList = $this->ci->listCitask($orderBy, $pager); - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = $this->lang->citask->common; - - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->module = 'citask'; - $this->display(); - } - - /** - * Create a ci task. - * - * @access public - * @return void - */ - public function createCitask() - { - if($_POST) - { - $this->ci->createCitask(); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseCitask'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->citask->create . $this->lang->colon . $this->lang->citask->common; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseCitask'), $this->lang->citask->common); - $this->view->position[] = $this->lang->citask->create; - - $this->view->repoList = $this->ci->listRepoForSelection("true"); - $this->view->jenkinsList = $this->ci->listJenkinsForSelection("true"); - $this->view->module = 'citask'; - - $this->display(); - } - - /** - * Edit a ci task. - * - * @param int $id - * @access public - * @return void - */ - public function editCitask($id) - { - $citask = $this->ci->getCitaskByID($id); - if($_POST) - { - $this->ci->updateCitask($id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseCitask'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->citask->edit . $this->lang->colon . $citask->name; - - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseCitask'), $this->lang->citask->common); - $this->view->position[] = $this->lang->citask->edit; - - $this->view->citask = $citask; - - $this->view->repoList = $this->ci->listRepoForSelection("true"); - $this->view->jenkinsList = $this->ci->listJenkinsForSelection("true"); - $this->view->module = 'citask'; - $this->display(); - } - - /** - * Delete a ci task. - * - * @param int $id - * @access public - * @return void - */ - public function deleteCitask($id) - { - $this->ci->delete(TABLE_CI_TASK, $id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $command = 'moduleName=ci&methodName=exeCitask&parm=' . $id; - $this->dao->delete()->from(TABLE_CRON)->where('command')->eq($command)->exec(); - - $this->send(array('result' => 'success')); - } - - /** - * Exec a ci task. - * - * @param int $id - * @access public - * @return void - */ - public function exeCitask($id) - { - error_log("===exeCitask " . $id); - - $this->ci->exeCitask($id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $this->send(array('result' => 'success')); - } - - /** - * Send a request to jenkins to check build status. - * - * @param int $buildID - * @access public - * @return void - */ - public function checkCibuild() - { - error_log("===checkCibuild"); - - $this->ci->checkCibuild(); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $this->send(array('result' => 'success')); - } - - /** - * Browse repo. - * - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browseRepo($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->ci->list; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = $this->lang->repo->common; - - $this->view->repoList = $this->ci->listRepo($orderBy, $pager); - - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->module = 'repo'; - $this->display(); - } - - /** - * Create a repo. - * - * @access public - * @return void - */ - public function createRepo() - { - if($_POST) - { - $repoID = $this->ci->createRepo(); - - if(dao::isError()) die(js::error(dao::getError())); - - $link = $this->ci->createLink('showSyncComment', "repoID=$repoID"); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link)); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->repo->create . $this->lang->colon . $this->lang->repo->common; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseRepo'), $this->lang->repo->common); - $this->view->position[] = $this->lang->repo->create; - - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); - - $this->view->credentialList = $this->ci->listCredentialForSelection("type='sshKey' or type='account'"); - $this->view->tips = str_replace("{user}",exec('whoami'), $this->lang->repo->tips); - $this->view->module = 'repo'; - - $this->display(); - } - - /** - * Edit a repo. - * - * @param int $repoID - * @access public - * @return void - */ - public function editRepo($repoID) - { - $repo = $this->ci->getRepoByID($repoID); - if($_POST) - { - $noNeedSync = $this->ci->updateRepo($repoID); - if(dao::isError()) die(js::error(dao::getError())); - if(!$noNeedSync) - { - $link = $this->ci->createLink('showSyncComment', "repoID=$repoID"); - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link)); - } - $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseRepo'))); - } - - $this->app->loadLang('action'); - $this->view->title = $this->lang->repo->edit . $this->lang->colon . $repo->name; - $this->view->position[] = $this->lang->ci->common; - $this->view->position[] = html::a(inlink('browseRepo'), $this->lang->repo->common); - $this->view->position[] = $this->lang->repo->edit; - - $this->view->repo = $repo; - - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); - - $this->view->credentialList = $this->ci->listCredentialForSelection("type='sshKey' or type='account'"); - $this->view->tips = str_replace("{user}", exec('whoami'), $this->lang->repo->tips); - $this->view->module = 'repo'; - $this->display(); - } - - /** - * Delete a repo. - * - * @param int $id - * @access public - * @return void - */ - public function deleteRepo($id) - { - $this->ci->delete(TABLE_REPO, $id); - if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - - $this->send(array('result' => 'success')); - } - - /** - * sync repo from remote. - * - * @param int $repoID - * @access public - * @return void - */ - public function syncRepo($repoID = 0) - { - $this->dao->update(TABLE_REPO)->set('synced')->eq(0)->where('id')->eq($repoID)->exec(); - - $link = $this->ci->createLink('showSyncComment', "repoID=$repoID&needPull=true"); - $this->send(array('result' => 'success', 'locate' => $link)); - } - - /** - * browse branches. - * - * @param int $repoID - * @access public - * @return void - */ - public function browseBranch($repoID = 0) - { - $repo = $this->ci->getRepoByID($repoID); - $branches = $this->ci->getBranchesFromDb($repoID); - - $this->view->repo = $repo; - $this->view->branches = $branches; - - $this->view->module = 'repo'; - $this->display(); - } - - /** - * watch branch. - * - * @param int $repoID - * @param int $branch - * @param int $status - */ - public function watchBranch($repoID = 0, $branch = 0, $status = 0) - { - $this->dao->update(TABLE_REPOBRANCH) - ->set('watch=' . $status) - ->where('repo')->eq($repoID) - ->andWhere('branch')->eq($branch) - ->exec(); - } - - /** - * Show sync comment. - * - * @param int $repoID - * @access public - * @return void - */ - public function showSyncComment($repoID = 0, $needPull = false) - { - if($repoID == 0) $repoID = $this->session->repoID; - - $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->showSyncComment; - $this->view->position[] = $this->lang->repo->showSyncComment; - - $latestInDB = $this->ci->getLatestComment($repoID, ); - $this->view->version = $latestInDB ? (int)$latestInDB->commit : 1; - $this->view->repoID = $repoID; - $this->view->needPull = $needPull; - $this->display(); - } - - /** - * Ajax sync comment. - * - * @param int $repoID - * @param string $type - * @access public - * @return void - */ - public function ajaxSyncComment($repoID = 0, $type = 'batch', $needPull = false) - { - set_time_limit(0); - $repo = $this->ci->getRepoByID($repoID); - - if ($needPull) { - $this->loadModel('git')->pull($repo); - } - - if(empty($repo)) die(); - if($repo->synced) die('finish'); - - $this->scm->setEngine($repo); - - $branchID = ''; - if($repo->SCM == 'Git' and empty($branchID)) - { - $branches = $this->scm->branch(); - if($branches) - { - /* Init branchID. */ - if($this->cookie->syncBranch) $branchID = $this->cookie->syncBranch; - if(!isset($branches[$branchID])) $branchID = ''; - if(empty($branchID)) $branchID = reset($branches); - - /* Get unsynced branches. */ - foreach($branches as $branch) - { - unset($branches[$branch]); - if($branch == $branchID) - { - break; - } - } - } - } - - $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($repo->SCM == 'Git' and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() - ->orderBy('t1.time') - ->limit(1) - ->fetch(); - - $version = empty($latestInDB) ? 1 : $latestInDB->commit + 1; - $logs = array(); - $revision = $version == 1 ? 'HEAD' : ($repo->SCM == 'Git' ? $latestInDB->commit : $latestInDB->revision); - if($type == 'batch') - { - $logs = $this->scm->getCommits($revision, $this->config->repo->batchNum, $branchID); - } - else - { - $logs = $this->scm->getCommits($revision, 0, $branchID); - } - - $commitCount = $this->ci->saveCommit($repoID, $logs, $version, $branchID); - if(empty($commitCount)) - { - if(!$repo->synced) - { - if($repo->SCM == 'Git') - { - if($branchID) $this->ci->saveExistsLogBranch($repo->id, $branchID); - - $branchID = reset($branches); - setcookie("syncBranch", $branchID, 0, $this->config->webRoot); - - if($branchID) $this->ci->fixCommit($repoID); - } - - if(empty($branchID)) - { - $this->ci->markSynced($repoID); - die('finish'); - } - } - } - - $this->dao->update(TABLE_REPO)->set('commits=commits + ' . $commitCount)->where('id')->eq($repoID)->exec(); - echo $type == 'batch' ? $commitCount : 'finish'; - } } \ No newline at end of file diff --git a/module/ci/js/browsecitask.js b/module/ci/js/browsecitask.js deleted file mode 100644 index 0a12f8df4f..0000000000 --- a/module/ci/js/browsecitask.js +++ /dev/null @@ -1,4 +0,0 @@ -$(function() -{ - -}) \ No newline at end of file diff --git a/module/ci/lang/zh-cn.php b/module/ci/lang/zh-cn.php index 4528e6719b..a23ff5594d 100644 --- a/module/ci/lang/zh-cn.php +++ b/module/ci/lang/zh-cn.php @@ -5,164 +5,7 @@ $lang->ci->create = '添加'; $lang->ci->numb = '序号'; $lang->ci->name = '名称'; -$lang->ci->subModules['credential'] = '凭证'; -$lang->ci->subModules['jenkins'] = 'Jenkins'; -$lang->ci->subModules['repo'] = '代码库'; -$lang->ci->subModules['citask'] = '构建任务'; - -// credential -$lang->credential->common = '凭证'; -$lang->credential->browse = '浏览凭证'; -$lang->credential->create = '添加凭证'; -$lang->credential->edit = '编辑凭证'; -$lang->credential->delete = '删除凭证'; -$lang->credential->confirmDelete = '确认删除该凭证吗?'; - -$lang->credential->id = 'ID'; -$lang->credential->name = '名称'; -$lang->credential->type = '类型'; -$lang->credential->username = '用户名'; -$lang->credential->password = '密码'; -$lang->credential->privateKey = '私钥'; -$lang->credential->passphrase = '私钥密码'; -$lang->credential->token = 'Token'; -$lang->credential->desc = '描述'; - -$lang->credential->typeList['account'] = '用户名密码'; -$lang->credential->typeList['sshKey'] = '密钥'; -$lang->credential->typeList['token'] = 'Token'; - -// jenkins -$lang->jenkins->common = 'Jenkins'; -$lang->jenkins->browse = '浏览Jenkins'; -$lang->jenkins->create = '添加Jenkins'; -$lang->jenkins->edit = '编辑Jenkins'; -$lang->jenkins->delete = '删除Jenkins'; -$lang->jenkins->confirmDelete = '确认删除该Jenkins吗?'; - -$lang->jenkins->id = 'ID'; -$lang->jenkins->name = '名称'; -$lang->jenkins->serviceUrl = '服务地址'; -$lang->jenkins->type = '认证方式'; -$lang->jenkins->credential = '凭证'; -$lang->jenkins->username = '用户名'; -$lang->jenkins->password = '密码'; -$lang->jenkins->token = 'Token'; -$lang->jenkins->desc = '描述'; -$lang->jenkins->tips = '选择用户名密码类型凭证时,请在Jenkins全局安全设置中禁用"防止跨站点请求伪造"选项。'; - -$lang->jenkins->typeList['token'] = 'Token'; -$lang->jenkins->typeList['credential'] = '凭证'; - -// ci task -$lang->citask->common = '构建任务'; -$lang->citask->browse = '浏览构建任务'; -$lang->citask->create = '添加构建任务'; -$lang->citask->edit = '编辑构建任务'; -$lang->citask->exeNow = '立即执行'; -$lang->citask->delete = '删除构建任务'; -$lang->citask->confirmDelete = '确认删除该构建任务吗?'; - -$lang->citask->id = 'ID'; -$lang->citask->name = '名称'; -$lang->citask->repo = '代码库'; -$lang->citask->jenkins = 'Jenkins服务'; -$lang->citask->jenkinsTask = 'Jenkins任务名'; -$lang->citask->buildType = '构建类型'; -$lang->citask->triggerType = '触发方式'; -$lang->citask->scheduleType = '时间计划'; -$lang->citask->cornExpression = 'Corn表达式'; -$lang->citask->custom = '自定义'; - -$lang->citask->tagKeywords = '标签关键字'; -$lang->citask->commentKeywords = '注释关键字'; -$lang->citask->extTask = '执行任务'; - -$lang->citask->at = '在'; -$lang->citask->time = '时间'; -$lang->citask->exe = '执行'; -$lang->citask->scheduleInterval = '每隔'; -$lang->citask->scheduleDay = '天数'; -$lang->citask->day = '天'; -$lang->citask->lastExe = '最后执行'; -$lang->citask->scheduleTime = '时间'; - -$lang->citask->example = '举例'; -$lang->citask->tagEx = 'build_#15,其中15为Jenkins任务编号'; -$lang->citask->commitEx = 'start build #15,其中15为Jenkins任务编号'; -$lang->citask->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点'; - -$lang->citask->dayTypeList = array('workDay'=>'工作日', 'everyDay'=>'每天'); -$lang->citask->buildTypeList = array('build'=>'仅构建', 'buildAndDeploy'=>'构建部署', 'buildAndTest'=>'构建测试'); -$lang->citask->triggerTypeList = array('tag'=>'打标签', 'commit'=>'代码提交注释', 'schedule'=>'定时计划'); -$lang->citask->scheduleTypeList = array('cron'=>'Cron表达式', 'custom'=>'自定义'); - -// repo -$lang->repo->common = '代码库'; -$lang->repo->browse = '浏览代码库'; -$lang->repo->create = '添加代码库'; -$lang->repo->edit = '编辑代码库'; -$lang->repo->delete = '删除代码库'; -$lang->repo->confirmDelete = '确认删除该代码库吗?'; -$lang->repo->browseBranch = '查看分支'; - -$lang->repo->id = 'ID'; -$lang->repo->name = '名称'; -$lang->repo->path = '地址'; -$lang->repo->type = '类型'; -$lang->repo->client = '客户端'; -$lang->repo->credential = '凭证'; -$lang->repo->encoding = '编码'; -$lang->repo->account = '用户名'; -$lang->repo->password = '密码'; -$lang->repo->token = 'Token'; -$lang->repo->acl = '权限'; -$lang->repo->group = '分组'; -$lang->repo->user = '用户'; -$lang->repo->desc = '描述'; - -$lang->repo->example = new stdclass(); -$lang->repo->example->client = "例如:/usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git"; -$lang->repo->example->path = "例如:SVN: http://example.googlecode.com/svn/, GIT: /homt/test"; -$lang->repo->example->config = "https需要填写配置目录的位置,通过config-dir选项生成配置目录"; -$lang->repo->example->encoding = "填写版本库中文件的编码"; -$lang->repo->svnCredentialLimt = "Subversion版本库的凭证必须为用户名密码类型"; - -$lang->repo->showSyncComment = '显示同步进度'; -$lang->repo->watch = '监听'; - -$lang->repo->notice = new stdclass(); -$lang->repo->notice->syncing = '正在同步中, 请稍等...'; -$lang->repo->notice->syncComplete = '同步完成,正在跳转...'; -$lang->repo->notice->syncedCount = '已经同步记录条数'; -$lang->repo->notice->delete = '是否要删除该版本库?'; -$lang->repo->notice->successDelete = '已经成功删除版本库。'; -$lang->repo->notice->commentContent = '输入回复内容'; -$lang->repo->notice->deleteBug = '确认删除该Bug?'; -$lang->repo->notice->deleteComment = '确认删除该回复?'; -$lang->repo->notice->lastSyncTime = '最后更新于:'; - -$lang->repo->error = new stdclass(); -$lang->repo->error->useless = '你的服务器禁用了exec,shell_exec方法,无法使用该功能'; -$lang->repo->error->connect = '连接版本库失败,请填写正确的用户名、密码和版本库地址!'; -$lang->repo->error->version = "https和svn协议需要1.8及以上版本的客户端,请升级到最新版本!详情访问:http://subversion.apache.org/"; -$lang->repo->error->path = '版本库地址直接填写文件路径,如:/home/test。'; -$lang->repo->error->cmd = '客户端错误!'; -$lang->repo->error->diff = '必须选择两个版本'; -$lang->repo->error->product = "请选择{$lang->productCommon}!"; -$lang->repo->error->commentText = '请填写评审内容'; -$lang->repo->error->comment = '请填写内容'; -$lang->repo->error->title = '请填写标题'; -$lang->repo->error->accessDenied = '你没有权限访问该版本库'; -$lang->repo->error->noFound = '你访问的版本库不存在'; -$lang->repo->error->noFile = '目录 %s 不存在'; -$lang->repo->error->noPriv = '程序没有权限切换到目录 %s'; -$lang->repo->error->output = "执行命令:%s\n错误结果(%s): %s\n"; -$lang->repo->error->clientVersion = "客户端版本过低,请升级或更换SVN客户端"; -$lang->repo->error->encoding = "编码可能错误,请更换编码重试。"; - -//$lang->repo->scmList['Subversion'] = 'Subversion'; -$lang->repo->scmList['Git'] = 'Git'; -$lang->repo->tips = '请使用用户{user}签出代码,以便于系统获取后续的代码同步权限。如:sudo -u {user} git clone git_rep_address'; - -$lang->repo->watchList['1'] = ''; \ No newline at end of file +$lang->ci->subModules['cicredentials'] = '凭证'; +$lang->ci->subModules['cijenkins'] = 'Jenkins'; +$lang->ci->subModules['cirepo'] = '代码库'; +$lang->ci->subModules['citask'] = '构建任务'; \ No newline at end of file diff --git a/module/ci/model.php b/module/ci/model.php index fdd15dc05e..1d32a01605 100644 --- a/module/ci/model.php +++ b/module/ci/model.php @@ -12,966 +12,5 @@ class ciModel extends model { - /** - * Get a credential by id. - * - * @param int $id - * @access public - * @return object - */ - public function getCredentialByID($id) - { - $credential = $this->dao->select('*')->from(TABLE_CREDENTIALS)->where('id')->eq($id)->fetch(); - return $credential; - } - /** - * Get credential list. - * - * @param string $orderBy - * @param object $pager - * @param bool $decode - * @access public - * @return array - */ - public function listCredential($orderBy = 'id_desc', $pager = null, $decode = true) - { - $credentials = $this->dao->select('*')->from(TABLE_CREDENTIALS) - ->where('deleted')->eq('0') - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - return $credentials; - } - - /** - * Create a credential. - * - * @access public - * @return bool - */ - public function createCredential() - { - $credential = fixer::input('post') - ->add('createdBy', $this->app->user->account) - ->add('createdDate', helper::now()) -// ->remove('') - ->get(); - - $this->dao->insert(TABLE_CREDENTIALS)->data($credential) - ->batchCheck($this->config->credential->create->requiredFields, 'notempty') - ->autoCheck() - ->exec(); - return !dao::isError(); - } - - /** - * Update a credential. - * - * @param int $id - * @access public - * @return bool - */ - public function updateCredential($id) - { - $credential = fixer::input('post') - ->add('editedBy', $this->app->user->account) - ->add('editedDate', helper::now()) - ->get(); - - $this->dao->update(TABLE_CREDENTIALS)->data($credential) - ->batchCheck($this->config->credential->edit->requiredFields, 'notempty') - ->autoCheck() - ->where('id')->eq($id) - ->exec(); - return !dao::isError(); - } - - - /** - * Get a jenkins by id. - * - * @param int $id - * @access public - * @return object - */ - public function getJenkinsByID($id) - { - $jenkins = $this->dao->select('*')->from(TABLE_JENKINS)->where('id')->eq($id)->fetch(); - return $jenkins; - } - - /** - * Get jenkins list. - * - * @param string $orderBy - * @param object $pager - * @param bool $decode - * @access public - * @return array - */ - public function listJenkins($orderBy = 'id_desc', $pager = null, $decode = true) - { - $jenkinsList = $this->dao->select('*')->from(TABLE_JENKINS) - ->where('deleted')->eq('0') - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - return $jenkinsList; - } - - /** - * Create a jenkins. - * - * @access public - * @return bool - */ - public function createJenkins() - { - $jenkins = fixer::input('post') - ->add('createdBy', $this->app->user->account) - ->add('createdDate', helper::now()) - ->get(); - - $this->dao->insert(TABLE_JENKINS)->data($jenkins) - ->batchCheck($this->config->jenkins->create->requiredFields, 'notempty') - ->batchCheck("serviceUrl", 'URL') - ->batchCheckIF($jenkins->type === 'credential', "credential", 'notempty') - ->autoCheck() - ->exec(); - return !dao::isError(); - } - - /** - * Update a jenkins. - * - * @param int $id - * @access public - * @return bool - */ - public function updateJenkins($id) - { - $jenkins = fixer::input('post') - ->add('editedBy', $this->app->user->account) - ->add('editedDate', helper::now()) - ->get(); - - $this->dao->update(TABLE_JENKINS)->data($jenkins) - ->batchCheck($this->config->jenkins->edit->requiredFields, 'notempty') - ->batchCheck("serviceUrl", 'URL') - ->batchCheckIF($jenkins->type === 'credential', "credential", 'notempty') - ->autoCheck() - ->where('id')->eq($id) - ->exec(); - return !dao::isError(); - } - - /** - * Get a ci task by id. - * - * @param int $id - * @access public - * @return object - */ - public function getCitaskByID($id) - { - $jenkins = $this->dao->select('*')->from(TABLE_CI_TASK)->where('id')->eq($id)->fetch(); - return $jenkins; - } - - /** - * Get ci task list. - * - * @param string $orderBy - * @param object $pager - * @param bool $decode - * @access public - * @return array - */ - public function listCitask($orderBy = 'id_desc', $pager = null, $decode = true) - { - $list = $this->dao-> - select('t1.*, t2.name repoName, t3.name as jenkinsName')->from(TABLE_CI_TASK)->alias('t1') - ->leftJoin(TABLE_REPO)->alias('t2')->on('t1.repo=t2.id') - ->leftJoin(TABLE_JENKINS)->alias('t3')->on('t1.jenkins=t3.id') - ->where('t1.deleted')->eq('0') - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - return $list; - } - - /** - * Create a ci task. - * - * @access public - * @return bool - */ - public function createCitask() - { - $task = fixer::input('post') - ->add('createdBy', $this->app->user->account) - ->add('createdDate', helper::now()) - ->get(); - - $this->dao->insert(TABLE_CI_TASK)->data($task) - ->batchCheck($this->config->citask->requiredFields, 'notempty') - ->batchCheckIF($task->triggerType === 'tag', "tagKeywords", 'notempty') - ->batchCheckIF($task->triggerType === 'commit', "commentKeywords", 'notempty') - - ->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'cron', "cronExpression", 'notempty') - ->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'custom', "scheduleDay,scheduleTime,scheduleInterval", 'notempty') - - ->autoCheck() - ->exec(); - - if ($task->triggerType === 'schedule') { - $taskId = $this->dao->lastInsertID(); - - if ($task->scheduleType == 'custom') { - $arr = explode(":", $task->scheduleTime); - $hour = $arr[0]; - $min = $arr[1]; - - if ($task->scheduleDay == 'everyDay') { - $days = '1-7'; - } else if ($task->scheduleDay == 'workDay') { - $days = '1-5'; - } - - $cron = (object)array('m' => $min, 'h' => $hour, 'dom' => '*', 'mon' => '*', - 'dow' => $days . '/' . $task->scheduleInterval, 'command' => 'moduleName=ci&methodName=exeCitask&parm=' . $taskId, - 'remark' => ($this->lang->citask->extTask . $taskId), 'type' => 'zentao', - 'buildin' => '-1', 'status' => 'normal', 'lastTime' => '0000-00-00 00:00:00'); - $this->dao->insert(TABLE_CRON)->data($cron)->exec(); - } else if ($task->scheduleType == 'cron') { - $arr = explode(' ', $task->cronExpression); - if (count($arr) >= 6) { - $cron = (object)array('m' => $arr[1], 'h' => $arr[2], 'dom' => $arr[3], 'mon' => $arr[4], - 'dow' => $arr[5], 'command' => 'moduleName=ci&methodName=exeCitask&parm=' . $taskId, - 'remark' => ($this->lang->citask->extTask . $taskId), 'type' => 'zentao', - 'buildin' => '-1', 'status' => 'normal', 'lastTime' => '0000-00-00 00:00:00'); - $this->dao->insert(TABLE_CRON)->data($cron)->exec(); - } - } - } - - return !dao::isError(); - } - - /** - * Update a ci task. - * - * @param int $id - * @access public - * @return bool - */ - public function updateCitask($id) - { - $task = fixer::input('post') - ->add('editedBy', $this->app->user->account) - ->add('editedDate', helper::now()) - ->get(); - - $this->dao->update(TABLE_CI_TASK)->data($task) - ->batchCheck($this->config->citask->requiredFields, 'notempty') - ->batchCheckIF($task->triggerType === 'tag', "tagKeywords", 'notempty') - ->batchCheckIF($task->triggerType === 'commit', "commentKeywords", 'notempty') - - ->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'cron', "cronExpression", 'notempty') - ->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'custom', "scheduleDay,scheduleTime,scheduleInterval", 'notempty') - - ->autoCheck() - ->where('id')->eq($id) - ->exec(); - - if ($task->triggerType === 'schedule') { - $command = 'moduleName=ci&methodName=exeCitask&parm=' . $id; - - if ($task->scheduleType == 'custom') { - $arr = explode(":", $task->scheduleTime); - $hour = $arr[0]; - $min = $arr[1]; - - $taskId = $this->dao->lastInsertID(); - if ($task->scheduleDay == 'everyDay') { - $days = '1-7'; - } else if ($task->scheduleDay == 'workDay') { - $days = '2-6'; - } - - $this->dao->update(TABLE_CRON) - ->set('m')->eq($min) - ->set('h')->eq($hour) - ->set('dom')->eq('*') - ->set('mon')->eq('*') - ->set('dow')->eq($days . '/' . $task->scheduleInterval) - ->set('lastTime')->eq('0000-00-00 00:00:00') - ->where('command')->eq($command)->exec(); - } else if ($task->scheduleType == 'cron') { - $arr = explode(' ', $task->cronExpression); - if (count($arr) >= 6) { - $this->dao->update(TABLE_CRON) - ->set('m')->eq($arr[1]) - ->set('h')->eq($arr[2]) - ->set('dom')->eq($arr[3]) - ->set('mon')->eq($arr[4]) - ->set('dow')->eq($arr[5]) - ->set('lastTime')->eq('0000-00-00 00:00:00') - ->where('command')->eq($command)->exec(); - } - } - } - - return !dao::isError(); - } - - /** - * Execute ci task. - * - * @param int $id - * @access public - * @return bool - */ - public function exeCitask($taskID) - { - $po = $this->dao->select('task.id taskId, task.name taskName, task.repo, task.jenkinsTask, jenkins.name jenkinsName,jenkins.serviceUrl,jenkins.credential') - ->from(TABLE_CI_TASK)->alias('task') - ->leftJoin(TABLE_JENKINS)->alias('jenkins')->on('task.jenkins=jenkins.id') - ->where('task.id')->eq($taskID) - ->fetch(); - - $credential = $this->getCredentialByID($po->credential); // jenkins must use a token or account credential - if ($credential->type === 'token') { - $jenkinsTokenOrPassword = $credential->token; - } else if ($credential->type === 'account') { - $jenkinsTokenOrPassword = $credential->password; - } - $jenkinsUser = $credential->username; - $jenkinsServer = $po->serviceUrl; - - $r = '://' . $jenkinsUser . ':' . $jenkinsTokenOrPassword . '@'; - $jenkinsServer = str_replace('://', $r, $jenkinsServer); - $buildUrl = sprintf('%s/job/%s/build/api/json', $jenkinsServer, $po->jenkinsTask); - - $po->queueItem = $this->sendBuildRequest($buildUrl); - $this->saveCibuild($po); - - return !dao::isError(); - } - /** - * Save build to db. - * - * @param object $task - * @access public - * @return bool - */ - public function saveCibuild($task) - { - $build = new stdClass(); - $build->citask = $task->taskId; - $build->name = $task->taskName . ' ' . helper::now(); - $build->queueItem = $task->queueItem; - $build->status = 'created'; - $build->createdBy = $this->app->user->account; - $build->createdDate = helper::now(); - - $this->dao->insert(TABLE_CI_BUILD)->data($build)->exec(); - } - - /** - * Update ci build status. - * - * @param object $task - * @access public - * @return bool - */ - public function updateCibuildStatus($buildId, $status) - { - $this->dao->update(TABLE_CI_BUILD)->set('status')->eq($status)->where('id')->eq($buildId)->exec(); - } - - /** - * Send a request to jenkins to check build status. - * - * @param int $buildID - * @access public - * @return bool - */ - public function checkCibuild() - { - $pos = $this->dao->select('build.*, task.jenkinsTask, jenkins.name jenkinsName,jenkins.serviceUrl,jenkins.credential') - ->from(TABLE_CI_BUILD)->alias('build') - ->leftJoin(TABLE_CI_TASK)->alias('task')->on('build.citask=task.id') - ->leftJoin(TABLE_JENKINS)->alias('jenkins')->on('task.jenkins=jenkins.id') - ->where('build.status')->ne('success') - ->andWhere('build.status')->ne('fail') - ->fetchAll(); - - foreach($pos as $po) { - $credential = $this->getCredentialByID($po->credential); // jenkins must use a token or account credential - if ($credential->type === 'token') { - $jenkinsTokenOrPassword = $credential->token; - } else if ($credential->type === 'account') { - $jenkinsTokenOrPassword = $credential->password; - } - $jenkinsUser = $credential->username; - $jenkinsServer = $po->serviceUrl; - - $r = '://' . $jenkinsUser . ':' . $jenkinsTokenOrPassword . '@'; - $jenkinsServer = str_replace('://', $r, $jenkinsServer); - $queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $po->queueItem); - - $response = common::http($queueUrl); - if (strripos($response,"404") > -1) { // queue已过期 - $infoUrl = sprintf('%s/job/%s/%s/api/json', $jenkinsServer, $po->jenkinsTask, $po->queueItem); - $response = common::http($infoUrl); - $buildInfo = json_decode($response); - $result = strtolower($buildInfo->result); - $this->updateCibuildStatus($po->id, $result); - - $logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $po->jenkinsTask, $po->queueItem); - $response = common::http($logUrl); - $logs = json_decode($response); - - $this->dao->update(TABLE_CI_BUILD)->set('logs')->eq($response)->where('id')->eq($po->id)->exec(); - } else { - $queueInfo = json_decode($response); - - if (!empty($queueInfo->executable)) { - $buildUrl = $queueInfo->executable->url . 'api/json?pretty=true'; - $buildUrl = str_replace('://', $r, $buildUrl); - - $response = common::http($buildUrl); - $buildInfo = json_decode($response); - - if ($buildInfo->building) { - $this->updateCibuildStatus($po->id, 'building'); - } else { - $result = strtolower($buildInfo->result); - $this->updateCibuildStatus($po->id, $result); - - $logUrl = $buildInfo->url . 'logText/progressiveText/api/json'; - $logUrl = str_replace('://', $r, $logUrl); - - $response = common::http($logUrl); - $logs = json_decode($response); - - $this->dao->update(TABLE_CI_BUILD)->set('logs')->eq($response)->where('id')->eq($po->id)->exec(); - } - } - } - } - } - - /** - * Get a repo by id. - * - * @param int $id - * @access public - * @return object - */ - public function getRepoByID($id) - { - $repo = $this->dao->select('*')->from(TABLE_REPO)->where('id')->eq($id)->fetch(); - return $repo; - } - - /** - * Get repo list. - * - * @param string $orderBy - * @param object $pager - * @param bool $decode - * @access public - * @return array - */ - public function listRepo($orderBy = 'id_desc', $pager = null, $decode = true) - { - $repoList = $this->dao->select('*')->from(TABLE_REPO) - ->where('deleted')->eq('0') - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - return $repoList; - } - - /** - * Create a repo. - * - * @access public - * @return bool - */ - public function createRepo() - { - $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); - if ($data->SCM === 'Subversion') { - $credential = $this->getCredentialByID($data->credential); - if ($credential->type != 'account') { - dao::$errors['credential'][] = $this->repo->svnCredentialLimt; - - return; - } - } - - $this->checkRepoConnection(); - $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); - - $data->acl = empty($data->acl) ? '' : json_encode($data->acl); - if(empty($data->client)) $data->client = 'svn'; - - if($data->SCM == 'Subversion') - { - $scm = $this->app->loadClass('scm'); - $scm->setEngine($data); - $info = $scm->info(''); - $data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/'); - if($data->prefix) $data->prefix = '/' . $data->prefix; - } - - if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->insert(TABLE_REPO)->data($data) - ->batchCheck($this->config->repo->create->requiredFields, 'notempty') - ->autoCheck() - ->exec(); - return $this->dao->lastInsertID(); - } - - /** - * Update a repo. - * - * @param int $id - * @access public - * @return bool - */ - public function updateRepo($repoID) - { - $this->checkRepoConnection(); - $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); - $data->acl = empty($data->acl) ? '' : json_encode($data->acl); - - if(empty($data->client)) $data->client = 'svn'; - $repo = $this->getRepoByID($repoID); - $data->prefix = $repo->prefix; - if($data->SCM == 'Subversion' and $data->path != $repo->path) - { - $scm = $this->app->loadClass('scm'); - $scm->setEngine($data); - $info = $scm->info(''); - $data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/'); - if($data->prefix) $data->prefix = '/' . $data->prefix; - } - elseif($data->SCM != $repo->SCM and $data->SCM == 'Git') - { - $data->prefix = ''; - } - - if($data->path != $repo->path) $data->synced = 0; - if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->update(TABLE_REPO)->data($data) - ->batchCheck($this->config->repo->create->requiredFields, 'notempty') - ->autoCheck() - ->where('id')->eq($repoID)->exec(); - if($repo->path != $data->path) - { - $this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->exec(); - $this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($repoID)->exec(); - return false; - } - return true; - } - - /** - * Get git branches from scm. - * - * @param object $repo - * @access public - * @return array - */ - public function getBranches($repo) - { - $this->scm = $this->app->loadClass('scm'); - $this->scm->setEngine($repo); - return $this->scm->branch(); - } - - /** - * Get git branches from db. - * - * @param object $repo - * @access public - * @return array - */ - public function getBranchesFromDb($repoID) - { - $branches = $this->dao->select('*')->from(TABLE_REPOBRANCH) - ->where('repo')->eq($repoID) - ->fetchAll('repo'); - return $branches; - } - - /** - * Check repo connection - * - * @access public - * @return void - */ - public function checkRepoConnection() - { - if(empty($_POST)) return false; - $scm = $this->post->SCM; - $client = $this->post->client; - $encoding = strtoupper($this->post->encoding); - $path = $this->post->path; - if($encoding != 'UTF8' and $encoding != 'UTF-8') $path = helper::convertEncoding($path, 'utf-8', $encoding); - - $account = ""; - $password = ""; - $privateKey = ""; - $passphrase = ""; - - $credential = $this->getCredentialByID($this->post->credential); - if ($credential->type === 'account') { - $account = $credential->username; - $password = $credential->password; - - $_POST['account'] = $account; - $_POST['password'] = $password; - } else { - $privateKey = $credential->privateKey; - $passphrase = $credential->passphrase; - - $_POST['privateKey'] = $privateKey; - $_POST['passphrase'] = $passphrase; - } - - if($scm == 'Subversion') - { - $path = '"' . $path . '"'; - if(stripos($path, 'https://') === 1 or stripos($path, 'svn://') === 1) - { - $ssh = true; - $remote = true; - $command = "$client info --username $account --password $password --non-interactive --trust-server-cert-failures=cn-mismatch --trust-server-cert --no-auth-cache $path 2>&1"; - } - else if(stripos($path, 'file://') === 1) - { - $ssh = false; - $remote = false; - $command = "$client info --non-interactive --no-auth-cache $path 2>&1"; - } - else - { - $ssh = false; - $remote = true; - $command = "$client info --username $account --password $password --non-interactive --no-auth-cache $path 2>&1"; - } - exec($command, $output, $result); - if($result) - { - $versionCommand = "$client --version --quiet 2>&1"; - exec($versionCommand, $versionOutput, $versionResult); - if($versionResult) - { - $message = sprintf($this->lang->repo->error->output, $versionCommand, $versionResult, join("\n", $versionOutput)); - echo $message; - die(js::alert($this->lang->repo->error->cmd . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); - } - if($ssh and version_compare(end($versionOutput), '1.6', '<')) die(js::alert($this->lang->repo->error->version)); - $message = sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output)); - echo $message; - if(stripos($message, 'Expected FS format between') !== false and strpos($message, 'found format') !== false) die(js::alert($this->lang->repo->error->clientVersion)); - if(preg_match('/[^\:\/\\A-Za-z0-9_\-\'\"]/', $path)) die(js::alert($this->lang->repo->error->encoding . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); - die(js::alert($this->lang->repo->error->connect . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); - } - } - elseif($scm == 'Git') - { - if(!chdir($path)) - { - if(!is_dir($path)) die(js::alert(sprintf($this->lang->repo->error->noFile, $path))); - if(!is_executable($path)) die(js::alert(sprintf($this->lang->repo->error->noPriv, $path))); - die(js::alert($this->lang->repo->error->path)); - } - - $command = "$client tag 2>&1"; - exec($command, $output, $result); - if($result) - { - echo sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output)); - die(js::alert($this->lang->repo->error->connect)); - } - } - return true; - } - - /** - * Get latest comment. - * - * @param int $repoID - * @access public - * @return object - */ - public function getLatestComment($repoID, $branchID='') - { - $count = $this->dao->select('count(DISTINCT t1.id) as count')->from(TABLE_REPOHISTORY)->alias('t1') - ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') - ->where('t1.repo')->eq($repoID) - ->beginIF($branchID)->andWhere('t2.branch')->eq($branchID)->fi() - ->fetch('count'); - - $lastComment = $this->dao->select('t1.*')->from(TABLE_REPOHISTORY)->alias('t1') - ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') - ->where('t1.repo')->eq($repoID) - ->beginIF($branchID)->andWhere('t2.branch')->eq($branchID)->fi() - ->orderBy('t1.time desc') - ->limit(1) - ->fetch(); - if(empty($lastComment)) return null; - - $repo = $this->getRepoByID($repoID); - if($repo->SCM == 'Git' and $lastComment->commit != $count) - { - $this->fixCommit($repo->id); - $lastComment->commit = $count; - } - - return $lastComment; - } - - /** - * Save commit. - * - * @param int $repoID - * @param array $logs - * @param int $version - * @param string $branch - * @access public - * @return int - */ - public function saveCommit($repoID, $logs, $version, $branch = '') - { - $count = 0; - if(empty($logs)) return $count; - - foreach($logs['commits'] as $i => $commit) - { - $existsRevision = $this->dao->select('id,revision')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('revision')->eq($commit->revision)->fetch(); - if($existsRevision) - { - if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($existsRevision->id)->set('branch')->eq($branch)->exec(); - continue; - } - - $commit->repo = $repoID; - $commit->commit = $version; - $commit->comment = htmlspecialchars($commit->comment); - $this->dao->insert(TABLE_REPOHISTORY)->data($commit)->exec(); - if(!dao::isError()) - { - $commitID = $this->dao->lastInsertID(); - if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($commitID)->set('branch')->eq($branch)->exec(); - foreach($logs['files'][$i] as $file) - { - $parentPath = dirname($file->path); - - $file->parent = $parentPath == '\\' ? '/' : $parentPath; - $file->revision = $commitID; - $file->repo = $repoID; - $this->dao->insert(TABLE_REPOFILES)->data($file)->exec(); - } - $revisionPairs[$commit->revision] = $commit->revision; - $version++; - $count++; - } - else - { - dao::getError(); - } - } - return $count; - } - - /** - * Save exists log branch. - * - * @param int $repoID - * @param string $branch - * @access public - * @return void - */ - public function saveExistsLogBranch($repoID, $branch) - { - $lastBranchLog = $this->dao->select('t1.time')->from(TABLE_REPOHISTORY)->alias('t1') - ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') - ->where('t1.repo')->eq($repoID) - ->andWhere('t2.branch')->eq($branch) - ->orderBy('time') - ->limit(1) - ->fetch(); - $stmt = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('time')->lt($lastBranchLog->time)->query(); - while($log = $stmt->fetch()) - { - $this->dao->REPLACE(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($log->id)->set('branch')->eq($branch)->exec(); - } - } - - /** - * Fix commit. - * - * @param int $repoID - * @access public - * @return void - */ - public function fixCommit($repoID) - { - $stmt = $this->dao->select('DISTINCT t1.id')->from(TABLE_REPOHISTORY)->alias('t1') - ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') - ->where('t1.repo')->eq($repoID) -// ->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() - ->orderBy('time') - ->query(); - - $i = 1; - while($repoHistory = $stmt->fetch()) - { - $this->dao->update(TABLE_REPOHISTORY)->set('`commit`')->eq($i)->where('id')->eq($repoHistory->id)->exec(); - $i++; - } - } - - /** - * Mark synced status. - * - * @param int $repoID - * @access public - * @return void - */ - public function markSynced($repoID) - { - $this->fixCommit($repoID); - $this->dao->update(TABLE_REPO)->set('synced')->eq(1)->where('id')->eq($repoID)->exec(); - } - - /** - * Create link for repo - * - * @param string $method - * @param string $params - * @param string $pathParams - * @param string $viewType - * @param bool $onlybody - * @access public - * @return string - */ - public function createLink($method, $params = '', $pathParams = '', $viewType = '', $onlybody = false) - { - $link = helper::createLink('ci', $method, $params, $viewType, $onlybody); - if(empty($pathParams)) return $link; - - $link .= strpos($link, '?') === false ? '?' : '&'; - $link .= $pathParams; - return $link; - } - - /** - * list credential for repo and jenkins edit page - * - * @param $whr - * @return mixed - */ - public function listCredentialForSelection($whr) - { - $credentials = $this->dao->select('id, name')->from(TABLE_CREDENTIALS) - ->where('deleted')->eq('0') - ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() - ->orderBy(id) - ->fetchPairs(); - $credentials[''] = ''; - return $credentials; - } - - /** - * list repos for jenkins task edit - * - * @return mixed - */ - public function listRepoForSelection($whr) - { - $repos = $this->dao->select('id, name')->from(TABLE_REPO) - ->where('deleted')->eq('0') - ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() - ->orderBy(id) - ->fetchPairs(); - $repos[''] = ''; - return $repos; - } - - /** - * list repos for jenkins task edit - * - * @return mixed - */ - public function listRepoForSync($whr) - { - $repos = $this->dao->select('*')->from(TABLE_REPO) - ->where('deleted')->eq('0') - ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() - ->orderBy(id) - ->fetchAll(); - return $repos; - } - - /** - * list jenkins for ci task edit - * - * @return mixed - */ - public function listJenkinsForSelection($whr) - { - $repos = $this->dao->select('id, name')->from(TABLE_JENKINS) - ->where('deleted')->eq('0') - ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() - ->orderBy(id) - ->fetchPairs(); - $repos[''] = ''; - return $repos; - } - - public static function sendBuildRequest($url) - { - if(!extension_loaded('curl')) return json_encode(array('result' => 'fail', 'message' => $lang->error->noCurlExt)); - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_setopt($curl, CURLOPT_USERAGENT, 'Sae T OAuth2 v0.1'); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); - curl_setopt($curl, CURLOPT_TIMEOUT, 30); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($curl, CURLOPT_ENCODING, ""); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); - curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - curl_setopt($curl, CURLOPT_HEADER, FALSE); - - $headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR']; - curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE); -// - curl_setopt ($curl , CURLOPT_HEADER, 1 ); - - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, new stdClass()); - - $response = curl_exec($curl); - $errors = curl_error($curl); - curl_close($curl); - - if ( preg_match ( "!Location: .*item/(.*)/!", $response , $matches ) ) { - return $matches[1]; - } - - return ''; - } } diff --git a/module/ci/view/header.html.php b/module/ci/view/header.html.php index 5148069ae1..5729bd404b 100644 --- a/module/ci/view/header.html.php +++ b/module/ci/view/header.html.php @@ -18,8 +18,7 @@
methodName !== 'browsebranch' && strpos($this->methodName,'browse') > -1 && common::hasPriv($module, 'create')) { - echo html::a(inlink('create' . $module), - " {$lang->ci->create}{$lang->ci->subModules[$module]}", + echo html::a(inlink('create'), " {$lang->ci->create}", '', "class='btn btn-primary'"); } else if($this->methodName == 'browsebranch') { echo html::backButton(); diff --git a/module/ci/view/menu.html.php b/module/ci/view/menu.html.php index d5e9b1cfa7..b36dec3f5d 100644 --- a/module/ci/view/menu.html.php +++ b/module/ci/view/menu.html.php @@ -4,7 +4,7 @@
ci->subModules as $key => $value) { - echo html::a(inlink('browse' . $key, '', ''), ''.$value.'', '', " id='{$key}Tab'"); + echo html::a($this->createLink($key, 'browse', ""), ''.$value.'', '', " id='{$key}Tab'"); } ?>
diff --git a/module/cicredentials/config.php b/module/cicredentials/config.php new file mode 100644 index 0000000000..d9322817ea --- /dev/null +++ b/module/cicredentials/config.php @@ -0,0 +1,3 @@ +credential->create->requiredFields = 'name,serviceUrl'; +$config->credential->edit->requiredFields = 'name,serviceUrl'; \ No newline at end of file diff --git a/module/cicredentials/control.php b/module/cicredentials/control.php new file mode 100644 index 0000000000..1282ea1234 --- /dev/null +++ b/module/cicredentials/control.php @@ -0,0 +1,119 @@ + + * @package product + * @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $ + * @link http://www.zentao.net + */ +class cicredentials extends control +{ + /** + * ci constructor. + * @param string $moduleName + * @param string $methodName + */ + public function __construct($moduleName = '', $methodName = '') + { + parent::__construct($moduleName, $methodName); + } + + /** + * Browse credentials + * + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + */ + public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $this->view->title = $this->lang->credential->common . $this->lang->colon . $this->lang->ci->list; + $this->view->credentialsList = $this->cicredentials->listAll($orderBy, $pager); + + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = $this->lang->credentials->common; + + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->view->module = 'cicredentials'; + $this->display(); + } + + /** + * Create a credentials. + * + * @access public + * @return void + */ + public function create() + { + if($_POST) + { + $this->cicredentials->create(); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->credentials->create . $this->lang->colon . $this->lang->credential->common; + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->credentials->common); + $this->view->position[] = $this->lang->credentials->create; + + $this->view->module = 'cicredentials'; + $this->display(); + } + + /** + * Edit a credentials. + * + * @param int $id + * @access public + * @return void + */ + public function edit($id) + { + $credentials = $this->cicredentials->getByID($id); + if($_POST) + { + $this->cicredentials->update($id); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->credentials->edit . $this->lang->colon . $credentials->name; + + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->credentials->common); + $this->view->position[] = $this->lang->credentials->edit; + + $this->view->credentials = $credentials; + + $this->view->module = 'cicredentials'; + $this->display(); + } + + /** + * Delete a credentials. + * + * @param int $id + * @access public + * @return void + */ + public function delete($id) + { + $this->cicredentials->delete(TABLE_CREDENTIALS, $id); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $this->send(array('result' => 'success')); + } +} \ No newline at end of file diff --git a/module/ci/js/browsecredential.js b/module/cicredentials/js/browse.js similarity index 100% rename from module/ci/js/browsecredential.js rename to module/cicredentials/js/browse.js diff --git a/module/ci/js/createcredential.js b/module/cicredentials/js/create.js similarity index 100% rename from module/ci/js/createcredential.js rename to module/cicredentials/js/create.js diff --git a/module/ci/js/editcredential.js b/module/cicredentials/js/edit.js similarity index 100% rename from module/ci/js/editcredential.js rename to module/cicredentials/js/edit.js diff --git a/module/cicredentials/lang/en.php b/module/cicredentials/lang/en.php new file mode 100644 index 0000000000..b3d9bbc7f3 --- /dev/null +++ b/module/cicredentials/lang/en.php @@ -0,0 +1 @@ +credentials->common = '凭证'; +$lang->credentials->browse = '浏览凭证'; +$lang->credentials->create = '添加凭证'; +$lang->credentials->edit = '编辑凭证'; +$lang->credentials->delete = '删除凭证'; +$lang->credentials->confirmDelete = '确认删除该凭证吗?'; + +$lang->credentials->id = 'ID'; +$lang->credentials->name = '名称'; +$lang->credentials->type = '类型'; +$lang->credentials->username = '用户名'; +$lang->credentials->password = '密码'; +$lang->credentials->privateKey = '私钥'; +$lang->credentials->passphrase = '私钥密码'; +$lang->credentials->token = 'Token'; +$lang->credentials->desc = '描述'; + +$lang->credentials->typeList['account'] = '用户名密码'; +$lang->credentials->typeList['sshKey'] = '密钥'; +$lang->credentials->typeList['token'] = 'Token'; \ No newline at end of file diff --git a/module/cicredentials/model.php b/module/cicredentials/model.php new file mode 100644 index 0000000000..415f150b5e --- /dev/null +++ b/module/cicredentials/model.php @@ -0,0 +1,106 @@ + + * @package product + * @version $Id: $ + * @link http://www.zentao.net + */ + +class cicredentialsModel extends model +{ + /** + * Get a credentials by id. + * + * @param int $id + * @access public + * @return object + */ + public function getByID($id) + { + $credential = $this->dao->select('*')->from(TABLE_CREDENTIALS)->where('id')->eq($id)->fetch(); + return $credential; + } + + /** + * Get credentials list. + * + * @param string $orderBy + * @param object $pager + * @param bool $decode + * @access public + * @return array + */ + public function listAll($orderBy = 'id_desc', $pager = null, $decode = true) + { + $credentials = $this->dao->select('*')->from(TABLE_CREDENTIALS) + ->where('deleted')->eq('0') + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + return $credentials; + } + + /** + * Create a credentials. + * + * @access public + * @return bool + */ + public function create() + { + $credential = fixer::input('post') + ->add('createdBy', $this->app->user->account) + ->add('createdDate', helper::now()) +// ->remove('') + ->get(); + + $this->dao->insert(TABLE_CREDENTIALS)->data($credential) + ->batchCheck($this->config->credential->create->requiredFields, 'notempty') + ->autoCheck() + ->exec(); + return !dao::isError(); + } + + /** + * Update a credentials. + * + * @param int $id + * @access public + * @return bool + */ + public function update($id) + { + $credential = fixer::input('post') + ->add('editedBy', $this->app->user->account) + ->add('editedDate', helper::now()) + ->get(); + + $this->dao->update(TABLE_CREDENTIALS)->data($credential) + ->batchCheck($this->config->credential->edit->requiredFields, 'notempty') + ->autoCheck() + ->where('id')->eq($id) + ->exec(); + return !dao::isError(); + } + + /** + * list credentials for repo and jenkins edit page + * + * @param $whr + * @return mixed + */ + public function listForSelection($whr) + { + $credentials = $this->dao->select('id, name')->from(TABLE_CREDENTIALS) + ->where('deleted')->eq('0') + ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() + ->orderBy(id) + ->fetchPairs(); + $credentials[''] = ''; + return $credentials; + } +} diff --git a/module/ci/view/browsecredential.html.php b/module/cicredentials/view/browse.html.php similarity index 62% rename from module/ci/view/browsecredential.html.php rename to module/cicredentials/view/browse.html.php index c8ef56d0c9..9a21017ac8 100644 --- a/module/ci/view/browsecredential.html.php +++ b/module/cicredentials/view/browse.html.php @@ -1,6 +1,6 @@ - -credential->confirmDelete); ?> + + +credentials->confirmDelete); ?>
- +
recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; ?> - - - + + + - $credential): ?> + $credentials): ?> - - + + @@ -48,7 +49,7 @@
credential->id); ?>credential->type); ?>credential->name); ?>credentials->id); ?>credentials->type); ?>credentials->name); ?> actions; ?>
credential->typeList, $credential->type); ?>name; ?>credentials->typeList, $credentials->type); ?>name; ?> createLink('ci', 'deleteCredential', "credentialID=$id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"credentialList\", confirmDelete)", '', '', "title='{$lang->credential->delete}' class='btn'"); + common::printIcon('cicredentials', 'edit', "id=$id", '', 'list', 'edit'); + if (common::hasPriv('cicredentials', 'delete')) { + $deleteURL = $this->createLink('cicredentials', 'delete', "id=$id&confirm=yes"); + echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"credentialsList\", confirmDelete)", '', '', "title='{$lang->credentials->delete}' class='btn'"); } ?>
- +
diff --git a/module/ci/view/createcredential.html.php b/module/cicredentials/view/create.html.php similarity index 77% rename from module/ci/view/createcredential.html.php rename to module/cicredentials/view/create.html.php index 5682caac9c..94f76d8782 100644 --- a/module/ci/view/createcredential.html.php +++ b/module/cicredentials/view/create.html.php @@ -10,62 +10,63 @@ * @link http://www.zentao.net */ ?> - + +
-

credential->create; ?>

+

credentials->create; ?>

- - + + - + - + - + - + - + - + - + diff --git a/module/ci/view/editcredential.html.php b/module/cicredentials/view/edit.html.php similarity index 65% rename from module/ci/view/editcredential.html.php rename to module/cicredentials/view/edit.html.php index 39a09f0c53..6634234544 100644 --- a/module/ci/view/editcredential.html.php +++ b/module/cicredentials/view/edit.html.php @@ -10,62 +10,63 @@ * @link http://www.zentao.net */ ?> - + + -type)?> +type)?>
-

credential->edit; ?>

+

credentials->edit; ?>

credential->type; ?>credential->typeList, 'account', "class='form-control'"); ?>credentials->type; ?>credentials->typeList, 'account', "class='form-control'"); ?>
credential->name; ?>credentials->name; ?>
credential->username; ?>credentials->username; ?>
credential->password; ?>credentials->password; ?>
credential->privateKey; ?>credentials->privateKey; ?>
credential->passphrase; ?>credentials->passphrase; ?>
credential->token; ?>credentials->token; ?>
credential->desc; ?>credentials->desc; ?>
- - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/module/cijenkins/config.php b/module/cijenkins/config.php new file mode 100644 index 0000000000..29957d0657 --- /dev/null +++ b/module/cijenkins/config.php @@ -0,0 +1,3 @@ +jenkins->create->requiredFields = 'name,serviceUrl,credentials'; +$config->jenkins->edit->requiredFields = 'name,serviceUrl,credentials'; \ No newline at end of file diff --git a/module/cijenkins/control.php b/module/cijenkins/control.php new file mode 100644 index 0000000000..95254bda2a --- /dev/null +++ b/module/cijenkins/control.php @@ -0,0 +1,124 @@ + + * @package product + * @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $ + * @link http://www.zentao.net + */ +class cijenkins extends control +{ + /** + * cijenkins constructor. + * @param string $moduleName + * @param string $methodName + */ + public function __construct($moduleName = '', $methodName = '') + { + parent::__construct($moduleName, $methodName); + } + + /** + * Browse jenkinss. + * + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $this->view->title = $this->lang->jenkins->common . $this->lang->colon . $this->lang->ci->list; + $this->view->jenkinsList = $this->cijenkins->listAll($orderBy, $pager); + + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = $this->lang->jenkins->common; + + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->view->module = 'cijenkins'; + $this->display(); + } + + /** + * Create a jenkins. + * + * @access public + * @return void + */ + public function create() + { + if($_POST) + { + $this->cijenkins->create(); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->jenkins->create . $this->lang->colon . $this->lang->jenkins->common; + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->jenkins->common); + $this->view->position[] = $this->lang->jenkins->create; + + $this->view->credentialsList = $this->loadModel('cicredentials')->listForSelection("type='token' or type='account'"); + $this->view->module = 'cijenkins'; + + $this->display(); + } + + /** + * Edit a jenkins. + * + * @param int $id + * @access public + * @return void + */ + public function edit($id) + { + $jenkins = $this->cijenkins->getByID($id); + if($_POST) + { + $this->cijenkins->update($id); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->jenkins->edit . $this->lang->colon . $jenkins->name; + + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->jenkins->common); + $this->view->position[] = $this->lang->jenkins->edit; + + $this->view->jenkins = $jenkins; + $this->view->credentialsList = $this->loadModel('cicredentials')->listForSelection("type='token' or type='account'"); + + $this->view->module = 'cijenkins'; + $this->display(); + } + + /** + * Delete a jenkins. + * + * @param int $id + * @access public + * @return void + */ + public function delete($id) + { + $this->cijenkins->delete(TABLE_JENKINS, $id); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $this->send(array('result' => 'success')); + } +} \ No newline at end of file diff --git a/module/ci/js/browsejenkins.js b/module/cijenkins/js/browse.js similarity index 100% rename from module/ci/js/browsejenkins.js rename to module/cijenkins/js/browse.js diff --git a/module/ci/js/createjenkins.js b/module/cijenkins/js/create.js similarity index 100% rename from module/ci/js/createjenkins.js rename to module/cijenkins/js/create.js diff --git a/module/ci/js/editjenkins.js b/module/cijenkins/js/edit.js similarity index 100% rename from module/ci/js/editjenkins.js rename to module/cijenkins/js/edit.js diff --git a/module/cijenkins/lang/en.php b/module/cijenkins/lang/en.php new file mode 100644 index 0000000000..b3d9bbc7f3 --- /dev/null +++ b/module/cijenkins/lang/en.php @@ -0,0 +1 @@ +jenkins->common = 'Jenkins'; +$lang->jenkins->browse = '浏览Jenkins'; +$lang->jenkins->create = '添加Jenkins'; +$lang->jenkins->edit = '编辑Jenkins'; +$lang->jenkins->delete = '删除Jenkins'; +$lang->jenkins->confirmDelete = '确认删除该Jenkins吗?'; + +$lang->jenkins->id = 'ID'; +$lang->jenkins->name = '名称'; +$lang->jenkins->serviceUrl = '服务地址'; +$lang->jenkins->type = '认证方式'; +$lang->jenkins->credential = '凭证'; +$lang->jenkins->username = '用户名'; +$lang->jenkins->password = '密码'; +$lang->jenkins->token = 'Token'; +$lang->jenkins->desc = '描述'; +$lang->jenkins->tips = '选择用户名密码类型凭证时,请在Jenkins全局安全设置中禁用"防止跨站点请求伪造"选项。'; + +$lang->jenkins->typeList['token'] = 'Token'; +$lang->jenkins->typeList['credential'] = '凭证'; diff --git a/module/cijenkins/model.php b/module/cijenkins/model.php new file mode 100644 index 0000000000..d4d63b2cf8 --- /dev/null +++ b/module/cijenkins/model.php @@ -0,0 +1,107 @@ + + * @package product + * @version $Id: $ + * @link http://www.zentao.net + */ + +class cijenkinsModel extends model +{ + /** + * Get a jenkins by id. + * + * @param int $id + * @access public + * @return object + */ + public function getByID($id) + { + $jenkins = $this->dao->select('*')->from(TABLE_JENKINS)->where('id')->eq($id)->fetch(); + return $jenkins; + } + + /** + * Get jenkins list. + * + * @param string $orderBy + * @param object $pager + * @param bool $decode + * @access public + * @return array + */ + public function listAll($orderBy = 'id_desc', $pager = null, $decode = true) + { + $jenkinsList = $this->dao->select('*')->from(TABLE_JENKINS) + ->where('deleted')->eq('0') + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + return $jenkinsList; + } + + /** + * Create a jenkins. + * + * @access public + * @return bool + */ + public function create() + { + $jenkins = fixer::input('post') + ->add('createdBy', $this->app->user->account) + ->add('createdDate', helper::now()) + ->get(); + + $this->dao->insert(TABLE_JENKINS)->data($jenkins) + ->batchCheck($this->config->jenkins->create->requiredFields, 'notempty') + ->batchCheck("serviceUrl", 'URL') + ->autoCheck() + ->exec(); + return !dao::isError(); + } + + /** + * Update a jenkins. + * + * @param int $id + * @access public + * @return bool + */ + public function update($id) + { + $jenkins = fixer::input('post') + ->add('editedBy', $this->app->user->account) + ->add('editedDate', helper::now()) + ->get(); + + $this->dao->update(TABLE_JENKINS)->data($jenkins) + ->batchCheck($this->config->jenkins->edit->requiredFields, 'notempty') + ->batchCheck("serviceUrl", 'URL') + ->batchCheckIF($jenkins->type === 'credential', "credential", 'notempty') + ->autoCheck() + ->where('id')->eq($id) + ->exec(); + return !dao::isError(); + } + + /** + * list jenkins for ci task edit + * + * @return mixed + */ + public function listForSelection($whr) + { + $repos = $this->dao->select('id, name')->from(TABLE_JENKINS) + ->where('deleted')->eq('0') + ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() + ->orderBy(id) + ->fetchPairs(); + $repos[''] = ''; + return $repos; + } +} diff --git a/module/ci/view/browsejenkins.html.php b/module/cijenkins/view/browse.html.php similarity index 87% rename from module/ci/view/browsejenkins.html.php rename to module/cijenkins/view/browse.html.php index b9f618103b..bec0e65f82 100644 --- a/module/ci/view/browsejenkins.html.php +++ b/module/cijenkins/view/browse.html.php @@ -10,12 +10,13 @@ * @link http://www.zentao.net */ ?> - + +jenkins->confirmDelete); ?>
@@ -38,9 +39,9 @@
credential->type; ?>credential->typeList, $credential->type, "class='form-control'"); ?>credentials->type; ?>credentials->typeList, $credentials->type, "class='form-control'"); ?>
credential->name; ?>name, "class='form-control'"); ?>credentials->name; ?>name, "class='form-control'"); ?>
credential->username; ?>username, "class='form-control'"); ?>credentials->username; ?>username, "class='form-control'"); ?>
credential->password; ?>password, "class='form-control'"); ?>credentials->password; ?>password, "class='form-control'"); ?>
credential->privateKey; ?>privateKey, "rows='3' class='form-control'"); ?>credentials->privateKey; ?>privateKey, "rows='3' class='form-control'"); ?>
credential->passphrase; ?>passphrase, "rows='3' class='form-control'"); ?>credentials->passphrase; ?>passphrase, "rows='3' class='form-control'"); ?>
credential->token; ?>token, "class='form-control'"); ?>credentials->token; ?>token, "class='form-control'"); ?>
credential->desc; ?>desc, "rows='3' class='form-control'"); ?>credentials->desc; ?>desc, "rows='3' class='form-control'"); ?>
createLink('ci', 'deleteJenkins', "jenkinsID=$id&confirm=yes"); + common::printIcon('cijenkins', 'edit', "jenkinsID=$id", '', 'list', 'edit'); + if (common::hasPriv('cijenkins', 'delete')) { + $deleteURL = $this->createLink('cijenkins', 'delete', "jenkinsID=$id&confirm=yes"); echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"jenkinsList\", confirmDelete)", '', '', "title='{$lang->jenkins->delete}' class='btn'"); } ?> @@ -49,7 +50,7 @@
- +
diff --git a/module/ci/view/createjenkins.html.php b/module/cijenkins/view/create.html.php similarity index 90% rename from module/ci/view/createjenkins.html.php rename to module/cijenkins/view/create.html.php index 987da3ba2f..f692e3d3d1 100644 --- a/module/ci/view/createjenkins.html.php +++ b/module/cijenkins/view/create.html.php @@ -10,12 +10,13 @@ * @link http://www.zentao.net */ ?> - + +
@@ -35,8 +36,8 @@ - credential->common; ?> - + credentials->common; ?> + jenkins->tips; ?> diff --git a/module/ci/view/editjenkins.html.php b/module/cijenkins/view/edit.html.php similarity index 89% rename from module/ci/view/editjenkins.html.php rename to module/cijenkins/view/edit.html.php index 2365a83a71..660561486e 100644 --- a/module/ci/view/editjenkins.html.php +++ b/module/cijenkins/view/edit.html.php @@ -10,12 +10,13 @@ * @link http://www.zentao.net */ ?> - + +
@@ -35,8 +36,8 @@ - credential->common; ?> - credential, "class='form-control'"); ?> + credentials->common; ?> + credentials, "class='form-control'"); ?> jenkins->tips; ?> diff --git a/module/cirepo/config.php b/module/cirepo/config.php new file mode 100644 index 0000000000..edcff96df5 --- /dev/null +++ b/module/cirepo/config.php @@ -0,0 +1,8 @@ +repo->create->requiredFields = 'SCM,name,path,encoding,client,credential'; +$config->repo->edit->requiredFields = 'SCM,name,path,encoding,client,credential'; +$config->repo->cacheTime = 10; +$config->repo->syncTime = 10; +$config->repo->batchNum = 100; +$config->repo->images = '|png|gif|jpg|ico|jpeg|bmp|'; +$config->repo->binary = '|pdf|'; \ No newline at end of file diff --git a/module/cirepo/control.php b/module/cirepo/control.php new file mode 100644 index 0000000000..1ded2d97f0 --- /dev/null +++ b/module/cirepo/control.php @@ -0,0 +1,303 @@ + + * @package product + * @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $ + * @link http://www.zentao.net + */ +class cirepo extends control +{ + /** + * ci constructor. + * @param string $moduleName + * @param string $methodName + */ + public function __construct($moduleName = '', $methodName = '') + { + parent::__construct($moduleName, $methodName); + $this->scm = $this->app->loadClass('scm'); + } + + /** + * Browse repo. + * + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->ci->list; + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = $this->lang->repo->common; + + $this->view->repoList = $this->cirepo->listAll($orderBy, $pager); + + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->view->module = 'cirepo'; + $this->display(); + } + + /** + * Create a repo. + * + * @access public + * @return void + */ + public function create() + { + if($_POST) + { + $repoID = $this->cirepo->create(); + + if(dao::isError()) die(js::error(dao::getError())); + + $link = $this->cirepo->createLink('showSyncComment', "repoID=$repoID"); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link)); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->repo->create . $this->lang->colon . $this->lang->repo->common; + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->repo->common); + $this->view->position[] = $this->lang->repo->create; + + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); + + $this->view->credentialsList = $this->loadModel('cicredentials')->listForSelection("type='sshKey' or type='account'"); + $this->view->tips = str_replace("{user}",exec('whoami'), $this->lang->repo->tips); + $this->view->module = 'cirepo'; + + $this->display(); + } + + /** + * Edit a repo. + * + * @param int $repoID + * @access public + * @return void + */ + public function edit($repoID) + { + $repo = $this->cirepo->getByID($repoID); + if($_POST) + { + $noNeedSync = $this->cirepo->update($repoID); + if(dao::isError()) die(js::error(dao::getError())); + if(!$noNeedSync) + { + $link = $this->cirepo->createLink('showSyncComment', "repoID=$repoID"); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link)); + } + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + } + + $this->app->loadLang('action'); + $this->view->title = $this->lang->repo->edit . $this->lang->colon . $repo->name; + $this->view->position[] = $this->lang->ci->common; + $this->view->position[] = html::a(inlink('browse'), $this->lang->repo->common); + $this->view->position[] = $this->lang->repo->edit; + + $this->view->repo = $repo; + + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); + + $this->view->credentialsList = $this->loadModel('cicredentials')->listForSelection("type='sshKey' or type='account'"); + $this->view->tips = str_replace("{user}", exec('whoami'), $this->lang->repo->tips); + $this->view->module = 'cirepo'; + $this->display(); + } + + /** + * Delete a repo. + * + * @param int $id + * @access public + * @return void + */ + public function delete($id) + { + $this->cirepo->delete(TABLE_REPO, $id); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $this->send(array('result' => 'success')); + } + + /** + * sync repo from remote. + * + * @param int $repoID + * @access public + * @return void + */ + public function sync($repoID = 0) + { + $this->dao->update(TABLE_REPO)->set('synced')->eq(0)->where('id')->eq($repoID)->exec(); + + $link = $this->cirepo->createLink('showSyncComment', "repoID=$repoID&needPull=true"); + $this->send(array('result' => 'success', 'locate' => $link)); + } + + /** + * browse branches. + * + * @param int $repoID + * @access public + * @return void + */ + public function browseBranch($repoID = 0) + { + $repo = $this->cirepo->getByID($repoID); + $branches = $this->cirepo->getBranchesFromDb($repoID); + + $this->view->repo = $repo; + $this->view->branches = $branches; + + $this->view->module = 'cirepo'; + $this->display(); + } + + /** + * watch branch. + * + * @param int $repoID + * @param int $branch + * @param int $status + */ + public function watchBranch($repoID = 0, $branch = 0, $status = 0) + { + $this->dao->update(TABLE_REPOBRANCH) + ->set('watch=' . $status) + ->where('repo')->eq($repoID) + ->andWhere('branch')->eq($branch) + ->exec(); + } + + /** + * Show sync comment. + * + * @param int $repoID + * @access public + * @return void + */ + public function showSyncComment($repoID = 0, $needPull = false) + { + if($repoID == 0) $repoID = $this->session->repoID; + + $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->showSyncComment; + $this->view->position[] = $this->lang->repo->showSyncComment; + + $latestInDB = $this->cirepo->getLatestComment($repoID); + $this->view->version = $latestInDB ? (int)$latestInDB->commit : 1; + $this->view->repoID = $repoID; + $this->view->needPull = $needPull; + $this->display(); + } + + /** + * Ajax sync comment. + * + * @param int $repoID + * @param string $type + * @access public + * @return void + */ + public function ajaxSyncComment($repoID = 0, $type = 'batch', $needPull = false) + { + set_time_limit(0); + $repo = $this->cirepo->getByID($repoID); + + if ($needPull) { + $this->loadModel('git')->pull($repo); + } + + if(empty($repo)) die(); + if($repo->synced) die('finish'); + + $this->scm->setEngine($repo); + + $branchID = ''; + if($repo->SCM == 'Git' and empty($branchID)) + { + $branches = $this->scm->branch(); + if($branches) + { + /* Init branchID. */ + if($this->cookie->syncBranch) $branchID = $this->cookie->syncBranch; + if(!isset($branches[$branchID])) $branchID = ''; + if(empty($branchID)) $branchID = reset($branches); + + /* Get unsynced branches. */ + foreach($branches as $branch) + { + unset($branches[$branch]); + if($branch == $branchID) + { + break; + } + } + } + } + + $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($repo->SCM == 'Git' and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() + ->orderBy('t1.time') + ->limit(1) + ->fetch(); + + $version = empty($latestInDB) ? 1 : $latestInDB->commit + 1; + $logs = array(); + $revision = $version == 1 ? 'HEAD' : ($repo->SCM == 'Git' ? $latestInDB->commit : $latestInDB->revision); + if($type == 'batch') + { + $logs = $this->scm->getCommits($revision, $this->config->repo->batchNum, $branchID); + } + else + { + $logs = $this->scm->getCommits($revision, 0, $branchID); + } + + $commitCount = $this->cirepo->saveCommit($repoID, $logs, $version, $branchID); + if(empty($commitCount)) + { + if(!$repo->synced) + { + if($repo->SCM == 'Git') + { + if($branchID) $this->cirepo->saveExistsLogBranch($repo->id, $branchID); + + $branchID = reset($branches); + setcookie("syncBranch", $branchID, 0, $this->config->webRoot); + + if($branchID) $this->cirepo->fixCommit($repoID); + } + + if(empty($branchID)) + { + $this->cirepo->markSynced($repoID); + die('finish'); + } + } + } + + $this->dao->update(TABLE_REPO)->set('commits=commits + ' . $commitCount)->where('id')->eq($repoID)->exec(); + echo $type == 'batch' ? $commitCount : 'finish'; + } +} \ No newline at end of file diff --git a/module/ci/js/browserepo.js b/module/cirepo/js/browse.js similarity index 100% rename from module/ci/js/browserepo.js rename to module/cirepo/js/browse.js diff --git a/module/ci/js/browsebranch.js b/module/cirepo/js/browsebranch.js similarity index 74% rename from module/ci/js/browsebranch.js rename to module/cirepo/js/browsebranch.js index 07f6e9ba98..14efa1564f 100644 --- a/module/ci/js/browsebranch.js +++ b/module/cirepo/js/browsebranch.js @@ -10,7 +10,7 @@ function watch(ths){ var repoID = elem.attr('data-repo'); var branch = elem.attr('data-branch'); - var link = createLink('ci', 'watchBranch', "repoID=" + repoID + "&branch=" + branch + "&status=" + newVal); + var link = createLink('cirepo', 'watchBranch', "repoID=" + repoID + "&branch=" + branch + "&status=" + newVal); console.log(link); $.get(link, function(data) { diff --git a/module/ci/js/createrepo.js b/module/cirepo/js/create.js similarity index 100% rename from module/ci/js/createrepo.js rename to module/cirepo/js/create.js diff --git a/module/ci/js/editrepo.js b/module/cirepo/js/edit.js similarity index 100% rename from module/ci/js/editrepo.js rename to module/cirepo/js/edit.js diff --git a/module/cirepo/lang/en.php b/module/cirepo/lang/en.php new file mode 100644 index 0000000000..b3d9bbc7f3 --- /dev/null +++ b/module/cirepo/lang/en.php @@ -0,0 +1 @@ +repo->common = '代码库'; +$lang->repo->browse = '浏览代码库'; +$lang->repo->create = '添加代码库'; +$lang->repo->edit = '编辑代码库'; +$lang->repo->delete = '删除代码库'; +$lang->repo->confirmDelete = '确认删除该代码库吗?'; +$lang->repo->browseBranch = '查看分支'; + +$lang->repo->id = 'ID'; +$lang->repo->name = '名称'; +$lang->repo->path = '地址'; +$lang->repo->type = '类型'; +$lang->repo->client = '客户端'; +$lang->repo->credential = '凭证'; +$lang->repo->encoding = '编码'; +$lang->repo->account = '用户名'; +$lang->repo->password = '密码'; +$lang->repo->token = 'Token'; +$lang->repo->acl = '权限'; +$lang->repo->group = '分组'; +$lang->repo->user = '用户'; +$lang->repo->desc = '描述'; + +$lang->repo->example = new stdclass(); +$lang->repo->example->client = "例如:/usr/bin/svn, C:\subversion\svn.exe, /usr/bin/git"; +$lang->repo->example->path = "例如:SVN: http://example.googlecode.com/svn/, GIT: /homt/test"; +$lang->repo->example->config = "https需要填写配置目录的位置,通过config-dir选项生成配置目录"; +$lang->repo->example->encoding = "填写版本库中文件的编码"; +$lang->repo->svnCredentialLimt = "Subversion版本库的凭证必须为用户名密码类型"; + +$lang->repo->showSyncComment = '显示同步进度'; +$lang->repo->watch = '监听'; + +$lang->repo->notice = new stdclass(); +$lang->repo->notice->syncing = '正在同步中, 请稍等...'; +$lang->repo->notice->syncComplete = '同步完成,正在跳转...'; +$lang->repo->notice->syncedCount = '已经同步记录条数'; +$lang->repo->notice->delete = '是否要删除该版本库?'; +$lang->repo->notice->successDelete = '已经成功删除版本库。'; +$lang->repo->notice->commentContent = '输入回复内容'; +$lang->repo->notice->deleteBug = '确认删除该Bug?'; +$lang->repo->notice->deleteComment = '确认删除该回复?'; +$lang->repo->notice->lastSyncTime = '最后更新于:'; + +$lang->repo->error = new stdclass(); +$lang->repo->error->useless = '你的服务器禁用了exec,shell_exec方法,无法使用该功能'; +$lang->repo->error->connect = '连接版本库失败,请填写正确的用户名、密码和版本库地址!'; +$lang->repo->error->version = "https和svn协议需要1.8及以上版本的客户端,请升级到最新版本!详情访问:http://subversion.apache.org/"; +$lang->repo->error->path = '版本库地址直接填写文件路径,如:/home/test。'; +$lang->repo->error->cmd = '客户端错误!'; +$lang->repo->error->diff = '必须选择两个版本'; +$lang->repo->error->product = "请选择{$lang->productCommon}!"; +$lang->repo->error->commentText = '请填写评审内容'; +$lang->repo->error->comment = '请填写内容'; +$lang->repo->error->title = '请填写标题'; +$lang->repo->error->accessDenied = '你没有权限访问该版本库'; +$lang->repo->error->noFound = '你访问的版本库不存在'; +$lang->repo->error->noFile = '目录 %s 不存在'; +$lang->repo->error->noPriv = '程序没有权限切换到目录 %s'; +$lang->repo->error->output = "执行命令:%s\n错误结果(%s): %s\n"; +$lang->repo->error->clientVersion = "客户端版本过低,请升级或更换SVN客户端"; +$lang->repo->error->encoding = "编码可能错误,请更换编码重试。"; + +//$lang->repo->scmList['Subversion'] = 'Subversion'; +$lang->repo->scmList['Git'] = 'Git'; +$lang->repo->tips = '请使用用户{user}签出代码,以便于系统获取后续的代码同步权限。如:sudo -u {user} git clone git_rep_address'; + +$lang->repo->watchList['1'] = ''; \ No newline at end of file diff --git a/module/cirepo/model.php b/module/cirepo/model.php new file mode 100644 index 0000000000..035f0d6bfd --- /dev/null +++ b/module/cirepo/model.php @@ -0,0 +1,456 @@ + + * @package product + * @version $Id: $ + * @link http://www.zentao.net + */ + +class cirepoModel extends model +{ + /** + * Get a repo by id. + * + * @param int $id + * @access public + * @return object + */ + public function getByID($id) + { + $repo = $this->dao->select('*')->from(TABLE_REPO)->where('id')->eq($id)->fetch(); + return $repo; + } + + /** + * Get repo list. + * + * @param string $orderBy + * @param object $pager + * @param bool $decode + * @access public + * @return array + */ + public function listAll($orderBy = 'id_desc', $pager = null, $decode = true) + { + $repoList = $this->dao->select('*')->from(TABLE_REPO) + ->where('deleted')->eq('0') + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + return $repoList; + } + + /** + * Create a repo. + * + * @access public + * @return bool + */ + public function create() + { + $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); + if ($data->SCM === 'Subversion') { + $credential = $this->loadModel('cicredentials')->getByID($data->credentials); + if ($credential->type != 'account') { + dao::$errors['credential'][] = $this->repo->svnCredentialLimt; + + return; + } + } + + $this->checkRepoConnection(); + $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); + + $data->acl = empty($data->acl) ? '' : json_encode($data->acl); + if(empty($data->client)) $data->client = 'svn'; + + if($data->SCM == 'Subversion') + { + $scm = $this->app->loadClass('scm'); + $scm->setEngine($data); + $info = $scm->info(''); + $data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/'); + if($data->prefix) $data->prefix = '/' . $data->prefix; + } + + if($data->encrypt == 'base64') $data->password = base64_encode($data->password); + $this->dao->insert(TABLE_REPO)->data($data) + ->batchCheck($this->config->repo->create->requiredFields, 'notempty') + ->autoCheck() + ->exec(); + return $this->dao->lastInsertID(); + } + + /** + * Update a repo. + * + * @param int $id + * @access public + * @return bool + */ + public function update($id) + { + $this->checkRepoConnection(); + $data = fixer::input('post')->skipSpecial('path,client,account,password')->get(); + $data->acl = empty($data->acl) ? '' : json_encode($data->acl); + + if(empty($data->client)) $data->client = 'svn'; + $repo = $this->getByID($id); + $data->prefix = $repo->prefix; + if($data->SCM == 'Subversion' and $data->path != $repo->path) + { + $scm = $this->app->loadClass('scm'); + $scm->setEngine($data); + $info = $scm->info(''); + $data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/'); + if($data->prefix) $data->prefix = '/' . $data->prefix; + } + elseif($data->SCM != $repo->SCM and $data->SCM == 'Git') + { + $data->prefix = ''; + } + + if($data->path != $repo->path) $data->synced = 0; + if($data->encrypt == 'base64') $data->password = base64_encode($data->password); + $this->dao->update(TABLE_REPO)->data($data) + ->batchCheck($this->config->repo->create->requiredFields, 'notempty') + ->autoCheck() + ->where('id')->eq($id)->exec(); + if($repo->path != $data->path) + { + $this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($id)->exec(); + $this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($id)->exec(); + return false; + } + return true; + } + + /** + * Get git branches from scm. + * + * @param object $repo + * @access public + * @return array + */ + public function getBranches($repo) + { + $this->scm = $this->app->loadClass('scm'); + $this->scm->setEngine($repo); + return $this->scm->branch(); + } + + /** + * Get git branches from db. + * + * @param object $repo + * @access public + * @return array + */ + public function getBranchesFromDb($repoID) + { + $branches = $this->dao->select('*')->from(TABLE_REPOBRANCH) + ->where('repo')->eq($repoID) + ->fetchAll('repo'); + return $branches; + } + + /** + * Check repo connection + * + * @access public + * @return void + */ + public function checkRepoConnection() + { + if(empty($_POST)) return false; + $scm = $this->post->SCM; + $client = $this->post->client; + $encoding = strtoupper($this->post->encoding); + $path = $this->post->path; + if($encoding != 'UTF8' and $encoding != 'UTF-8') $path = helper::convertEncoding($path, 'utf-8', $encoding); + + $account = ""; + $password = ""; + $privateKey = ""; + $passphrase = ""; + + $credential = $this->loadModel('cicredentials')->getByID($this->post->credentials); + if ($credential->type === 'account') { + $account = $credential->username; + $password = $credential->password; + + $_POST['account'] = $account; + $_POST['password'] = $password; + } else { + $privateKey = $credential->privateKey; + $passphrase = $credential->passphrase; + + $_POST['privateKey'] = $privateKey; + $_POST['passphrase'] = $passphrase; + } + + if($scm == 'Subversion') + { + $path = '"' . $path . '"'; + if(stripos($path, 'https://') === 1 or stripos($path, 'svn://') === 1) + { + $ssh = true; + $remote = true; + $command = "$client info --username $account --password $password --non-interactive --trust-server-cert-failures=cn-mismatch --trust-server-cert --no-auth-cache $path 2>&1"; + } + else if(stripos($path, 'file://') === 1) + { + $ssh = false; + $remote = false; + $command = "$client info --non-interactive --no-auth-cache $path 2>&1"; + } + else + { + $ssh = false; + $remote = true; + $command = "$client info --username $account --password $password --non-interactive --no-auth-cache $path 2>&1"; + } + exec($command, $output, $result); + if($result) + { + $versionCommand = "$client --version --quiet 2>&1"; + exec($versionCommand, $versionOutput, $versionResult); + if($versionResult) + { + $message = sprintf($this->lang->repo->error->output, $versionCommand, $versionResult, join("\n", $versionOutput)); + echo $message; + die(js::alert($this->lang->repo->error->cmd . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); + } + if($ssh and version_compare(end($versionOutput), '1.6', '<')) die(js::alert($this->lang->repo->error->version)); + $message = sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output)); + echo $message; + if(stripos($message, 'Expected FS format between') !== false and strpos($message, 'found format') !== false) die(js::alert($this->lang->repo->error->clientVersion)); + if(preg_match('/[^\:\/\\A-Za-z0-9_\-\'\"]/', $path)) die(js::alert($this->lang->repo->error->encoding . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); + die(js::alert($this->lang->repo->error->connect . '\n' . str_replace(array("\n", "'"), array('\n', '"'), $message))); + } + } + elseif($scm == 'Git') + { + if(!chdir($path)) + { + if(!is_dir($path)) die(js::alert(sprintf($this->lang->repo->error->noFile, $path))); + if(!is_executable($path)) die(js::alert(sprintf($this->lang->repo->error->noPriv, $path))); + die(js::alert($this->lang->repo->error->path)); + } + + $command = "$client tag 2>&1"; + exec($command, $output, $result); + if($result) + { + echo sprintf($this->lang->repo->error->output, $command, $result, join("\n", $output)); + die(js::alert($this->lang->repo->error->connect)); + } + } + return true; + } + + /** + * Get latest comment. + * + * @param int $repoID + * @access public + * @return object + */ + public function getLatestComment($repoID, $branchID='') + { + $count = $this->dao->select('count(DISTINCT t1.id) as count')->from(TABLE_REPOHISTORY)->alias('t1') + ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') + ->where('t1.repo')->eq($repoID) + ->beginIF($branchID)->andWhere('t2.branch')->eq($branchID)->fi() + ->fetch('count'); + + $lastComment = $this->dao->select('t1.*')->from(TABLE_REPOHISTORY)->alias('t1') + ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') + ->where('t1.repo')->eq($repoID) + ->beginIF($branchID)->andWhere('t2.branch')->eq($branchID)->fi() + ->orderBy('t1.time desc') + ->limit(1) + ->fetch(); + if(empty($lastComment)) return null; + + $repo = $this->getByID($repoID); + if($repo->SCM == 'Git' and $lastComment->commit != $count) + { + $this->fixCommit($repo->id); + $lastComment->commit = $count; + } + + return $lastComment; + } + + /** + * Save commit. + * + * @param int $repoID + * @param array $logs + * @param int $version + * @param string $branch + * @access public + * @return int + */ + public function saveCommit($repoID, $logs, $version, $branch = '') + { + $count = 0; + if(empty($logs)) return $count; + + foreach($logs['commits'] as $i => $commit) + { + $existsRevision = $this->dao->select('id,revision')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('revision')->eq($commit->revision)->fetch(); + if($existsRevision) + { + if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($existsRevision->id)->set('branch')->eq($branch)->exec(); + continue; + } + + $commit->repo = $repoID; + $commit->commit = $version; + $commit->comment = htmlspecialchars($commit->comment); + $this->dao->insert(TABLE_REPOHISTORY)->data($commit)->exec(); + if(!dao::isError()) + { + $commitID = $this->dao->lastInsertID(); + if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($commitID)->set('branch')->eq($branch)->exec(); + foreach($logs['files'][$i] as $file) + { + $parentPath = dirname($file->path); + + $file->parent = $parentPath == '\\' ? '/' : $parentPath; + $file->revision = $commitID; + $file->repo = $repoID; + $this->dao->insert(TABLE_REPOFILES)->data($file)->exec(); + } + $revisionPairs[$commit->revision] = $commit->revision; + $version++; + $count++; + } + else + { + dao::getError(); + } + } + return $count; + } + + /** + * Save exists log branch. + * + * @param int $repoID + * @param string $branch + * @access public + * @return void + */ + public function saveExistsLogBranch($repoID, $branch) + { + $lastBranchLog = $this->dao->select('t1.time')->from(TABLE_REPOHISTORY)->alias('t1') + ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') + ->where('t1.repo')->eq($repoID) + ->andWhere('t2.branch')->eq($branch) + ->orderBy('time') + ->limit(1) + ->fetch(); + $stmt = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->andWhere('time')->lt($lastBranchLog->time)->query(); + while($log = $stmt->fetch()) + { + $this->dao->REPLACE(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($log->id)->set('branch')->eq($branch)->exec(); + } + } + + /** + * Fix commit. + * + * @param int $repoID + * @access public + * @return void + */ + public function fixCommit($repoID) + { + $stmt = $this->dao->select('DISTINCT t1.id')->from(TABLE_REPOHISTORY)->alias('t1') + ->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision') + ->where('t1.repo')->eq($repoID) +// ->beginIF($this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi() + ->orderBy('time') + ->query(); + + $i = 1; + while($repoHistory = $stmt->fetch()) + { + $this->dao->update(TABLE_REPOHISTORY)->set('`commit`')->eq($i)->where('id')->eq($repoHistory->id)->exec(); + $i++; + } + } + + /** + * Mark synced status. + * + * @param int $repoID + * @access public + * @return void + */ + public function markSynced($repoID) + { + $this->fixCommit($repoID); + $this->dao->update(TABLE_REPO)->set('synced')->eq(1)->where('id')->eq($repoID)->exec(); + } + + /** + * Create link for repo + * + * @param string $method + * @param string $params + * @param string $pathParams + * @param string $viewType + * @param bool $onlybody + * @access public + * @return string + */ + public function createLink($method, $params = '', $pathParams = '', $viewType = '', $onlybody = false) + { + $link = helper::createLink('cirepo', $method, $params, $viewType, $onlybody); + if(empty($pathParams)) return $link; + + $link .= strpos($link, '?') === false ? '?' : '&'; + $link .= $pathParams; + return $link; + } + + /** + * list repos for jenkins task edit + * + * @return mixed + */ + public function listForSelection($whr) + { + $repos = $this->dao->select('id, name')->from(TABLE_REPO) + ->where('deleted')->eq('0') + ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() + ->orderBy(id) + ->fetchPairs(); + $repos[''] = ''; + return $repos; + } + + /** + * list repos for ci task edit + * + * @return mixed + */ + public function listForSync($whr) + { + $repos = $this->dao->select('*')->from(TABLE_REPO) + ->where('deleted')->eq('0') + ->beginIF(!empty(whr))->andWhere('(' . $whr . ')')->fi() + ->orderBy(id) + ->fetchAll(); + return $repos; + } + +} diff --git a/module/ci/view/browserepo.html.php b/module/cirepo/view/browse.html.php similarity index 84% rename from module/ci/view/browserepo.html.php rename to module/cirepo/view/browse.html.php index 0ea4bc97db..b04c6693f7 100644 --- a/module/ci/view/browserepo.html.php +++ b/module/cirepo/view/browse.html.php @@ -10,12 +10,13 @@ * @link http://www.zentao.net */ ?> - + + repo->confirmDelete); ?>
@@ -39,12 +40,12 @@ path; ?> createLink('ci', 'deleteRepo', "repoID=$id&confirm=yes"); + common::printIcon('cirepo', 'edit', "repoID=$id", '', 'list', 'edit'); + if (common::hasPriv('cirepo', 'delete')) { + $deleteURL = $this->createLink('cirepo', 'delete', "repoID=$id&confirm=yes"); echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"repoList\", confirmDelete)", '', '', "title='{$lang->repo->delete}' class='btn'"); } ?> @@ -53,7 +54,7 @@ - +
diff --git a/module/ci/view/browsebranch.html.php b/module/cirepo/view/browsebranch.html.php similarity index 73% rename from module/ci/view/browsebranch.html.php rename to module/cirepo/view/browsebranch.html.php index a917fcc625..854012e86b 100644 --- a/module/ci/view/browsebranch.html.php +++ b/module/cirepo/view/browsebranch.html.php @@ -10,11 +10,12 @@ * @link http://www.zentao.net */ ?> - + +
@@ -37,15 +38,7 @@ repo->watchList, $branch->watch, "data-branch='" . $branch->branch . "' data-repo='" . $branch->repo . "' onclick='watch(this)'");?> - - createLink('ci', 'deleteRepo', "branchID=$id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"branchList\", confirmDelete)", '', '', "title='{$lang->branch->delete}' class='btn'"); - } - ?> - + diff --git a/module/ci/view/createrepo.html.php b/module/cirepo/view/create.html.php similarity index 93% rename from module/ci/view/createrepo.html.php rename to module/cirepo/view/create.html.php index 1e5e576807..d45ad31810 100644 --- a/module/ci/view/createrepo.html.php +++ b/module/cirepo/view/create.html.php @@ -10,14 +10,15 @@ * @link http://www.zentao.net */ ?> - + +
@@ -56,8 +57,8 @@ repo->example->client;?> - credential->common; ?> - credential, "class='form-control'"); ?> + credentials->common; ?> + credentials, "class='form-control'"); ?> diff --git a/module/ci/view/editrepo.html.php b/module/cirepo/view/edit.html.php similarity index 93% rename from module/ci/view/editrepo.html.php rename to module/cirepo/view/edit.html.php index 388dc9c016..a3d8b9dc3c 100644 --- a/module/ci/view/editrepo.html.php +++ b/module/cirepo/view/edit.html.php @@ -10,14 +10,15 @@ * @link http://www.zentao.net */ ?> - + + type)?>
@@ -56,8 +57,8 @@ repo->example->client;?> - credential->common; ?> - credential, "class='form-control'"); ?> + credentials->common; ?> + credentials, "class='form-control'"); ?> diff --git a/module/ci/view/showsynccomment.html.php b/module/cirepo/view/showsynccomment.html.php similarity index 84% rename from module/ci/view/showsynccomment.html.php rename to module/cirepo/view/showsynccomment.html.php index b4759d9091..a1f3fb0b52 100644 --- a/module/ci/view/showsynccomment.html.php +++ b/module/cirepo/view/showsynccomment.html.php @@ -10,6 +10,7 @@ * @link http://www.zentao.net */ ?> +
@@ -25,7 +26,7 @@