control.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <?php
  2. /**
  3. * The control file of git module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Yanyi Cao <caoyanyi@easycorp.com>
  8. * @package git
  9. * @link https://www.zentao.net
  10. */
  11. class git extends control
  12. {
  13. /**
  14. * 定时任务:同步git。
  15. * Sync git.
  16. *
  17. * @access public
  18. * @return void
  19. */
  20. public function run()
  21. {
  22. $this->git->run();
  23. }
  24. /**
  25. * Git对比文件。
  26. * Diff a file.
  27. *
  28. * @param string $path
  29. * @param string $revision
  30. * @access public
  31. * @return void
  32. */
  33. public function diff($path, $revision)
  34. {
  35. if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
  36. $this->loadModel('repo');
  37. $path = helper::safe64Decode($path);
  38. $repos = $this->repo->getListBySCM(implode(',', $this->config->repo->gitTypeList), 'haspriv');
  39. $currentRepo = null;
  40. foreach($repos as $repo)
  41. {
  42. if(!empty($repo->path) && strpos($path, $repo->path) === 0) $currentRepo = $repo;
  43. if(!empty($repo->apiPath) && strpos($path, $repo->apiPath) === 0) $currentRepo = $repo;
  44. }
  45. if($currentRepo && common::hasPriv('repo', 'diff'))
  46. {
  47. $entry = $this->repo->encodePath(str_replace(array($currentRepo->path, $currentRepo->apiPath), '', $path));
  48. $oldRevision = "$revision^";
  49. return print($this->fetch('repo', 'diff', "repoID=$currentRepo->id&objectID=0&entry=$entry&oldRevision=$oldRevision&revision=$revision"));
  50. }
  51. if($currentRepo)
  52. {
  53. $scm = $this->app->loadClass('scm');
  54. $scm->setEngine($currentRepo);
  55. }
  56. $this->view->path = $path;
  57. $this->view->revision = $revision;
  58. $this->view->diff = $currentRepo ? $scm->diff($path, $revision) : '';
  59. $this->display();
  60. }
  61. /**
  62. * Git查看文件。
  63. * Cat a file.
  64. *
  65. * @param string $path
  66. * @param string $revision
  67. * @access public
  68. * @return void
  69. */
  70. public function cat($path, $revision)
  71. {
  72. if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
  73. $this->loadModel('repo');
  74. $path = helper::safe64Decode($path);
  75. $repos = $this->repo->getListBySCM(implode(',', $this->config->repo->gitTypeList), 'haspriv');
  76. $currentRepo = null;
  77. foreach($repos as $repo)
  78. {
  79. if(!empty($repo->path) && strpos($path, $repo->path) === 0) $currentRepo = $repo;
  80. if(!empty($repo->apiPath) && strpos($path, $repo->apiPath) === 0) $currentRepo = $repo;
  81. }
  82. if($currentRepo && common::hasPriv('repo', 'view'))
  83. {
  84. $entry = $this->repo->encodePath(str_replace(array($currentRepo->path, $repo->apiPath), '', $path));
  85. return print($this->fetch('repo', 'view', "repoID=$currentRepo->id&objectID=0&entry=$entry&revision=$revision"));
  86. }
  87. if($currentRepo)
  88. {
  89. $scm = $this->app->loadClass('scm');
  90. $scm->setEngine($currentRepo);
  91. }
  92. $this->view->path = $path;
  93. $this->view->revision = $revision;
  94. $this->view->code = $currentRepo ? $scm->cat($path, $revision) : '';
  95. $this->display();
  96. }
  97. /**
  98. * 通过api同步提交信息。
  99. * Sync from the syncer by api.
  100. *
  101. * @access public
  102. * @return void
  103. */
  104. public function apiSync()
  105. {
  106. if($this->post->logs) return;
  107. $repoRoot = $this->post->repoRoot;
  108. $list = json_decode($this->post->logs);
  109. $logs = array();
  110. $i = 0;
  111. foreach($list as $line)
  112. {
  113. if(!$line)
  114. {
  115. $i++;
  116. continue;
  117. }
  118. $logs[$i][] = $line;
  119. }
  120. foreach($logs as $log)
  121. {
  122. $log = $this->git->convertLog($log);
  123. if($log) $parsedLogs[] = $log;
  124. }
  125. $this->loadModel('repo');
  126. $parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array());
  127. foreach($parsedLogs as $log)
  128. {
  129. $objects = $this->repo->parseComment($log->msg);
  130. if($objects)
  131. {
  132. $this->git->saveAction2PMS($objects, $log, $repoRoot);
  133. if($objects['stories']) $parsedObjects['stories'] = array_merge($parsedObjects['stories'], $objects['stories']);
  134. if($objects['tasks']) $parsedObjects['tasks' ] = array_merge($parsedObjects['tasks'], $objects['tasks']);
  135. if($objects['bugs']) $parsedObjects['bugs'] = array_merge($parsedObjects['bugs'], $objects['bugs']);
  136. }
  137. }
  138. $parsedObjects['stories'] = array_unique($parsedObjects['stories']);
  139. $parsedObjects['tasks'] = array_unique($parsedObjects['tasks']);
  140. $parsedObjects['bugs'] = array_unique($parsedObjects['bugs']);
  141. $this->view->parsedObjects = $parsedObjects;
  142. return $this->display();
  143. }
  144. /**
  145. * 保存git提交日志。
  146. * Ajax save log.
  147. *
  148. * @access public
  149. * @return void
  150. */
  151. public function ajaxSaveLog()
  152. {
  153. $repoUrl = trim($this->post->repoUrl);
  154. $message = trim($this->post->message);
  155. $revision = trim($this->post->revision);
  156. $files = $this->post->files;
  157. if(empty($repoUrl)) return;
  158. $repoUrl = rtrim($repoUrl, '/') . '/';
  159. $parsedFiles = array();
  160. $repoDirs = explode('/', trim($repoUrl, '/'));
  161. foreach($files as $file)
  162. {
  163. $file = trim($file);
  164. if(empty($file)) continue;
  165. $action = '';
  166. if(preg_match('/^[\w][ \t]/', $file))
  167. {
  168. $action = $file[0];
  169. $file = trim(substr($file, 2));
  170. }
  171. $fileDirs = explode('/', trim($file, '/'));
  172. $diffDirs = array_diff($fileDirs, $repoDirs);
  173. foreach($fileDirs as $i => $dir)
  174. {
  175. if(isset($diffDirs[$i])) break;
  176. if(!isset($diffDirs[$i])) unset($fileDirs[$i]);
  177. }
  178. $path = '/' . join('/', $fileDirs);
  179. $parsedFiles[$action][] = ltrim($path, '/');
  180. }
  181. $objects = $this->loadModel('repo')->parseComment($message);
  182. if($objects)
  183. {
  184. $log = new stdclass();
  185. $log->author = $this->app->user->account;
  186. $log->date = helper::now();
  187. $log->msg = $message;
  188. $log->revision = $revision;
  189. $log->files = $parsedFiles;
  190. $this->git->saveAction2PMS($objects, $log, $repoUrl);
  191. }
  192. }
  193. /**
  194. * 获取代码库列表。
  195. * Ajax get repos.
  196. *
  197. * @access public
  198. * @return void
  199. */
  200. public function ajaxGetRepos()
  201. {
  202. $repos = $this->git->getRepos();
  203. echo json_encode($repos);
  204. }
  205. }