repo.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # -*- coding: utf-8 -*-
  2. """
  3. walle-web
  4. :copyright: © 2015-2019 walle-web.io
  5. :created time: 2019-02-24 10:47:53
  6. :author: wushuiyong@walle-web.io
  7. """
  8. import os
  9. import re
  10. import os.path as osp
  11. import getpass
  12. import git as PyGit
  13. from git import Repo as PyRepo
  14. from walle.model.record import RecordModel
  15. class Repo:
  16. '''
  17. @todo
  18. 需要把websocket接入
  19. '''
  20. path = None
  21. def __init__(self, path=None):
  22. self.path = path
  23. # What follows is the risk code for flake8.
  24. # def log(self, wenv):
  25. # '''
  26. #
  27. # @param wenv:
  28. #
  29. # @param stage:
  30. # @param sequence:
  31. # @param user_id:
  32. # @param task_id:
  33. # @param status:
  34. # @param host:
  35. # @param user:
  36. # @param command:
  37. # @param success:
  38. # @param error:
  39. #
  40. # @return:
  41. # '''
  42. # RecordModel().save_record(stage=wenv['stage'], sequence=wenv['sequence'], user_id=wenv['user_id'],
  43. # task_id=wenv['task_id'], status=exitcode, host='127.0.0.1', user=getpass.getuser(),
  44. # command=result.command, success=stdout,
  45. # error=stderr)
  46. #
  47. # def websocket(self):
  48. # ws_dict = {
  49. # 'user': getpass.getuser(),
  50. # 'host': '127.0.0.1',
  51. # 'cmd': command,
  52. # 'status': exitcode,
  53. # 'stage': wenv['stage'],
  54. # 'sequence': wenv['sequence'],
  55. # 'success': stdout,
  56. # 'error': stderr,
  57. # }
  58. # if wenv['console']:
  59. # emit('console', {'event': 'task:console', 'data': ws_dict}, room=wenv['task_id'])
  60. #
  61. # pass
  62. def is_git_dir(self):
  63. '''
  64. 判断是否为git目录
  65. @param path:
  66. @return:
  67. '''
  68. d = self.path + '/.git'
  69. if osp.isdir(d):
  70. if osp.isdir(osp.join(d, 'objects')) and osp.isdir(osp.join(d, 'refs')):
  71. headref = osp.join(d, 'HEAD')
  72. return osp.isfile(headref) or \
  73. (osp.islink(headref) and
  74. os.readlink(headref).startswith('refs'))
  75. elif (osp.isfile(osp.join(d, 'gitdir')) and
  76. osp.isfile(osp.join(d, 'commondir')) and
  77. osp.isfile(osp.join(d, 'gitfile'))):
  78. return False
  79. return False
  80. def init(self, url, branch="master"):
  81. # 创建目录
  82. if not os.path.exists(self.path):
  83. os.makedirs(self.path)
  84. # git clone
  85. if self.is_git_dir():
  86. self.checkout_2_branch(branch)
  87. return self.pull()
  88. else:
  89. return self.clone(url)
  90. def clone(self, url):
  91. '''
  92. 检出项目
  93. @param branch:
  94. @param kwargs:
  95. @return:
  96. '''
  97. return PyRepo.clone_from(url, self.path)
  98. def pull(self):
  99. '''
  100. 更新项目
  101. @param branch:
  102. @param kwargs:
  103. @return:
  104. '''
  105. repo = PyRepo(self.path)
  106. return repo.remote().pull()
  107. def checkout_2_branch(self, branch):
  108. '''
  109. 切换到某个分支
  110. @param branch:
  111. @return:
  112. '''
  113. PyRepo(self.path).git.checkout(branch)
  114. def checkout_2_commit(self, branch, commit):
  115. '''
  116. 切换分支的某个commit
  117. @param branch:
  118. @param commit:
  119. @return:
  120. '''
  121. self.checkout_2_branch(branch=branch)
  122. PyRepo(self.path).git.reset('--hard', commit)
  123. def checkout_2_tag(self, tag):
  124. '''
  125. 切换到tag
  126. @param tag:
  127. @return:
  128. '''
  129. PyRepo(self.path).git.checkout(tag)
  130. def branches(self):
  131. '''
  132. 获取所有分支
  133. @param branch:
  134. @param kwargs:
  135. @return:
  136. '''
  137. # 去除 origin/HEAD -> 当前指向
  138. # 去除远端前缀
  139. branches = PyRepo(self.path).remote().refs
  140. # fixbug https://github.com/meolu/walle-web/issues/705
  141. return [str(branch).strip().lstrip('origin').lstrip('/') for branch in branches if
  142. not str(branch).strip().startswith('origin/HEAD')]
  143. def tags(self):
  144. '''
  145. 获取所有tag,按时间倒序
  146. @param branch:
  147. @param kwargs:
  148. @return:
  149. '''
  150. return [str(tag) for tag in PyRepo(self.path).tags][-10:]
  151. def commits(self, branch):
  152. '''
  153. 获取分支的commits
  154. @param branch:
  155. @param kwargs:
  156. @return:
  157. '''
  158. self.checkout_2_branch(branch)
  159. commit_log = PyGit.Git(self.path).log('--pretty=%h #@_@# %an #@_@# %s', max_count=50)
  160. commit_list = commit_log.split('\n')
  161. commits = []
  162. for commit in commit_list:
  163. if not re.search('^.+ #@_@# .+ #@_@# .*$', commit):
  164. continue
  165. commit_dict = commit.split(' #@_@# ')
  166. from flask import current_app
  167. current_app.logger.info(commit_dict)
  168. commits.append({
  169. 'id': commit_dict[0],
  170. 'name': commit_dict[1],
  171. 'message': commit_dict[2],
  172. })
  173. return commits