/site/plugins/fatty/controllers/components/git.php

https://github.com/plastic/Cake-boilerplate · PHP · 304 lines · 206 code · 19 blank · 79 comment · 35 complexity · 29156658b42a097e7cd09a77f8a68ecc MD5 · raw file

  1. <?php
  2. /**
  3. * Fatty: Simple Git repogitory browser plugin for CakePHP.
  4. *
  5. */
  6. /**
  7. * GitComponent code license:
  8. *
  9. * @copyright Copyright (C) 2010 by 101000code/101000LAB
  10. * @since CakePHP(tm) v 1.2
  11. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  12. */
  13. set_time_limit(0);
  14. ini_set('memory_limit', '256M');
  15. require APP . 'plugins' . DS . 'fatty' . DS . 'config' . DS . 'core.php';
  16. class GitComponent extends Object {
  17. var $settings = array();
  18. var $enebled = true;
  19. var $controller;
  20. var $currentBranch = null;
  21. var $branches = array();
  22. /**
  23. * initialize
  24. *
  25. */
  26. function initialize(&$controller, $settings){
  27. if (Configure::read('debug') < 2 && empty($this->settings['forceEnable'])) {
  28. $this->enabled = false;
  29. return false;
  30. }
  31. }
  32. /**
  33. * startup
  34. *
  35. */
  36. function startup(&$controller){
  37. $controller->helpers['Fatty.Tip'] = array(
  38. 'forceEnable' => isset($this->settings['forceEnable'])? true : null,
  39. );
  40. $this->branch();
  41. }
  42. /**
  43. * beforeRender
  44. *
  45. * @return
  46. */
  47. function beforeRender(&$controller){
  48. $controller->set('fattyBranch', $this->currentBranch);
  49. }
  50. /**
  51. * branch
  52. * git branch
  53. *
  54. * @param
  55. * @return
  56. */
  57. function branch(){
  58. $cmd = 'GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " branch";
  59. $out = $this->_exec($cmd);
  60. $this->branches = array();
  61. foreach ($out as $value) {
  62. $this->branches[] = $value;
  63. if (preg_match('/^\* *([^ ]+)/', $value, $matches)) {
  64. $this->currentBranch = $matches[1];
  65. }
  66. }
  67. }
  68. /**
  69. * count
  70. * git log count
  71. *
  72. * @param
  73. * @return
  74. */
  75. function count($filepath = null){
  76. if ($filepath) {
  77. $root = preg_replace('/\.git\/*/', '', FATTY_GIT_DIR);
  78. $cmd = 'cd ' . $root . ';GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " log --pretty=oneline " . $root . $filepath . " | wc -l";
  79. } else {
  80. $cmd = 'GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " log --pretty=oneline | wc -l";
  81. }
  82. $out = $this->_exec($cmd);
  83. return $out[0];
  84. }
  85. /**
  86. * log
  87. * git log
  88. *
  89. * @param
  90. * @return
  91. */
  92. function log($limit = 20, $offset = 0, $filepath = null){
  93. if ($filepath) {
  94. $root = preg_replace('/\.git\/*/', '', FATTY_GIT_DIR);
  95. $cmd = 'cd ' . $root . ';GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " log --stat -n " . $limit . " --skip=" . $offset . " --parents " . $root . $filepath;
  96. } else {
  97. $cmd = 'GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " log --stat -n " . $limit . " --skip=" . $offset . " --parents";
  98. }
  99. $out = $this->_exec($cmd);
  100. $logs = array();
  101. foreach ($out as $line) {
  102. if (preg_match('/^commit ([\w]+) *([\w]*) *([\w]*)/',$line,$matches)) {
  103. $hash = $matches[1];
  104. $parent = $matches[2];
  105. $parent2 = $matches[3];
  106. $logs[$hash]['hash'] = $hash;
  107. $logs[$hash]['parent'] = $parent;
  108. $logs[$hash]['parent2'] = $parent2;
  109. }
  110. if (preg_match('/Author: ([\w]+)/',$line,$matches)) {
  111. $logs[$hash]['Author'] = $matches[1];
  112. }
  113. if (preg_match('/Date:[ ]*(.+)$/',$line,$matches)) {
  114. $logs[$hash]['Date'] = $matches[1];
  115. }
  116. if (preg_match('/^[ ]{4}(.+)$/',$line,$matches)) {
  117. if (empty($logs[$hash]['comment'])) {
  118. $logs[$hash]['comment'] = '';
  119. }
  120. $logs[$hash]['comment'] .= $matches[1] . "\n";
  121. }
  122. if (preg_match('/^[ ]([\w\/.]+)[ ]*\|[ ]*(.+)$/',$line,$matches)) {
  123. if (empty($logs[$hash]['files'])) {
  124. $logs[$hash]['files'] = array();
  125. }
  126. $logs[$hash]['files'][] = array('file' => $matches[1],
  127. 'change' => $matches[2]);
  128. }
  129. if (preg_match('/^[ ][\d]+ files.+/',$line,$matches)) {
  130. $logs[$hash]['change'] = $matches[0];
  131. }
  132. }
  133. return $logs;
  134. }
  135. /**
  136. * show
  137. * git show
  138. *
  139. * @param $hash
  140. * @return
  141. */
  142. function show($hash){
  143. $cmd = 'GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " show " . $hash . " --parents";
  144. $out = $this->_exec($cmd);
  145. $commit = array();
  146. $commit['comment'] = '';
  147. $commit['diff'] = array();
  148. $author = false;
  149. $date = false;
  150. $diff = false;
  151. $file = '';
  152. $part = 0;
  153. foreach ($out as $line) {
  154. if (preg_match('/^commit ([\w]+) *([\w]*) *([\w]*)/',$line,$matches)) {
  155. $hash = $matches[1];
  156. $parent = $matches[2];
  157. $parent2 = $matches[3];
  158. $commit['hash'] = $hash;
  159. $commit['parent'] = $parent;
  160. $commit['parent2'] = $parent2;
  161. continue;
  162. }
  163. if (preg_match('/Author: ([\w]+)/',$line,$matches) && !$author) {
  164. $author = true;
  165. $commit['Author'] = $matches[1];
  166. continue;
  167. }
  168. if (preg_match('/Date:[ ]*(.+)$/',$line,$matches) && !$date) {
  169. $date = true;
  170. $commit['Date'] = $matches[1];
  171. continue;
  172. }
  173. if (preg_match('/^[ ]{4}(.+)$/',$line,$matches) && !$diff) {
  174. $commit['comment'] .= $matches[1] . "\n";
  175. continue;
  176. }
  177. if (preg_match('/^diff --git a\/([^\s]+)/',$line,$matches)) {
  178. $diff = true;
  179. $file = $matches[1];
  180. $commit['diff'][$file] = array();
  181. continue;
  182. }
  183. if (preg_match('/^diff --cc ([^\s]+)/',$line,$matches)) {
  184. $diff = true;
  185. $file = $matches[1];
  186. $commit['diff'][$file] = array();
  187. continue;
  188. }
  189. if ($diff && $file && !preg_match('/^diff|^index|^\+\+\+|^---/',$line)) {
  190. if (preg_match('/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/',$line)) {
  191. $part++;
  192. $commit['diff'][$file][$part] = array();
  193. }
  194. $commit['diff'][$file][$part][] = $line;
  195. }
  196. }
  197. return $commit;
  198. }
  199. /**
  200. * diff
  201. *
  202. * @param $a
  203. * @param $b
  204. * @return
  205. */
  206. function diff($a = 'HEAD', $b = 'HEAD'){
  207. $cmd = 'GIT_DIR=' . FATTY_GIT_DIR . " " . FATTY_GIT_PATH . " diff " . $a . " " . $b;
  208. $out = $this->_exec($cmd);
  209. $commit = array();
  210. $commit['diff'] = array();
  211. $diff = false;
  212. $file = '';
  213. $part = 0;
  214. foreach ($out as $line) {
  215. if (preg_match('/^diff --git a\/([\w\/.]+)/',$line,$matches)) {
  216. $diff = true;
  217. $file = $matches[1];
  218. $commit['diff'][$file] = array();
  219. }
  220. if ($diff && $file && !preg_match('/^diff|^index|^\+\+\+|^---/',$line)) {
  221. if (preg_match('/^@@ -(\d+),(\d+) \+(\d+),(\d+) @@/',$line)) {
  222. $part++;
  223. $commit['diff'][$file][$part] = array();
  224. }
  225. $commit['diff'][$file][$part][] = $line;
  226. }
  227. }
  228. return $commit;
  229. }
  230. /**
  231. * blame
  232. *
  233. * @param $filepath
  234. * @return
  235. */
  236. function blame($filepath){
  237. $root = preg_replace('/\.git\/*/', '', FATTY_GIT_DIR);
  238. $cmd = 'cd ' . $root . ';' . FATTY_GIT_PATH . " blame -l" . " " . $root . $filepath;
  239. $out = $this->_exec($cmd);
  240. //pr($out);
  241. $blame = array();
  242. foreach ($out as $line) {
  243. if (preg_match('/^([0-9a-z^]+) \(([^ \)]+) +([^\)]+) +([\d]+)\) (.+)$/',$line,$matches)) {
  244. $blame[] = array('hash' => $matches[1],
  245. 'commiter' => $matches[2],
  246. 'date' => $matches[3],
  247. 'line' => $matches[4],
  248. 'code' => $matches[5]);
  249. }
  250. }
  251. return $blame;
  252. }
  253. /**
  254. * tree
  255. * ls-tree
  256. *
  257. * @param $hash
  258. * @return
  259. */
  260. function tree($hash = 'HEAD'){
  261. $root = preg_replace('/\.git\/*/', '', FATTY_GIT_DIR);
  262. $cmd = 'cd ' . $root . ';' . FATTY_GIT_PATH . " ls-tree " . $hash;
  263. $out = $this->_exec($cmd);
  264. $tree = array();
  265. foreach ($out as $file) {
  266. if (preg_match('/^[0-9]+ ([a-z]+) ([0-9a-z]+)\s(.+)/',$file,$matches)) {
  267. $tree[] = array('type' => $matches[1],
  268. 'hash' => $matches[2],
  269. 'name' => $matches[3]);
  270. }
  271. }
  272. return $tree;
  273. }
  274. /**
  275. * _exec
  276. *
  277. * @param $cmd
  278. * @return
  279. */
  280. function _exec($cmd) {
  281. $out = array();
  282. exec($cmd, $out);
  283. return $out;
  284. }
  285. }