coding.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. """
  4. @Contact : liuyuqi.gov@msn.cn
  5. @Time : 2023/09/27 10:35:25
  6. @License : Copyright © 2017-2022 liuyuqi. All Rights Reserved.
  7. @Desc : coding.net repo sync
  8. 两种授权: token 授权,OAuth2.0 授权
  9. """
  10. import os,subprocess,sys
  11. from repo_sync.platform.base_platform import BasePlatform
  12. from .project import Project
  13. from .repo import Repo
  14. class CodingIE(BasePlatform):
  15. """coding util"""
  16. client_id = ''
  17. client_serect = ''
  18. _host = 'https://e.coding.net' # 新版接口统一地址
  19. def __init__(self, username:str, token:str, host:str =None , params: dict = None) -> None:
  20. """init"""
  21. super().__init__(username , token)
  22. self.project_name = params.get('coding_project', '')
  23. self.repo_shared = False if params.get('coding_private', "true").lower() == 'true' else True
  24. self.url = f'{self._host}/open-api'
  25. def create_project(self):
  26. ''' createt a project '''
  27. data = {
  28. 'Action': 'CreateCodingProject',
  29. 'Name': '',
  30. 'DisplayName': '',
  31. 'Description': '',
  32. 'GitReadmeEnabled': False,
  33. 'VscType': 'git',
  34. 'CreateSvnLayout': False,
  35. 'Shared': 1,
  36. 'ProjectTemplateId': 'DEV_OPS',
  37. }
  38. r = self.sess.post(self.url, json=data)
  39. if r.status_code == 200:
  40. res_data = r.json()
  41. return True
  42. else:
  43. return False
  44. def delete_project(self):
  45. data = {
  46. 'Action': 'DeleteOneProject',
  47. 'ProjectId': 0,
  48. }
  49. r = self.sess.post(self.url, json=data)
  50. if r.status_code == 200:
  51. res_data = r.json()
  52. return True
  53. else:
  54. return False
  55. def get_project_list(self):
  56. pass
  57. def get_repo_list(self, username: str = None) -> list:
  58. """ get repo list from a project
  59. Args: username: the target username may not self.username
  60. return: repo list
  61. """
  62. data = {
  63. 'Action': 'DescribeTeamDepotInfoList',
  64. 'ProjectName': self.project_name,
  65. 'PageNumber': 1,
  66. 'PageSize': 50
  67. }
  68. r = self.sess.post(self.url, json=data)
  69. if r.status_code == 200:
  70. res_data = r.json()
  71. try:
  72. totalPage = res_data['Response']["DepotData"]["Page"]["TotalPage"]
  73. if totalPage > 0:
  74. currentPage = 1
  75. DepotList = []
  76. # the first page
  77. DepotList = res_data['Response']["DepotData"]["Depots"]
  78. repo_model = Repo(
  79. Id=DepotList[0]['Id'],
  80. Name=DepotList[0]['Name'],
  81. HttpsUrl=DepotList[0]['HttpsUrl'],
  82. ProjectId=DepotList[0]['ProjectId'],
  83. SshUrl=DepotList[0]['SshUrl'],
  84. WebUrl=DepotList[0]['WebUrl'],
  85. ProjectName=DepotList[0]['ProjectName'],
  86. Description=DepotList[0]['Description'],
  87. CreatedAt=DepotList[0]['CreatedAt'],
  88. GroupId=DepotList[0]['GroupId'],
  89. GroupName=DepotList[0]['GroupName']
  90. )
  91. DepotList.append(repo_model)
  92. currentPage += 1
  93. # the other pages
  94. for i in range(2, totalPage + 1):
  95. data = {
  96. 'Action': 'DescribeTeamDepotInfoList',
  97. 'ProjectName': self.project_name,
  98. 'PageNumber': currentPage,
  99. 'PageSize': 50
  100. }
  101. r = self.sess.post(self.url, json=data)
  102. res_data = r.json()
  103. DepotList = res_data['Response']["DepotData"]["Depots"]
  104. for repo in DepotList:
  105. repo_model= Repo(
  106. Id=repo['Id'],
  107. Name=repo['Name'],
  108. HttpsUrl=repo['HttpsUrl'],
  109. ProjectId=repo['ProjectId'],
  110. SshUrl=repo['SshUrl'],
  111. WebUrl=repo['WebUrl'],
  112. ProjectName=repo['ProjectName'],
  113. Description=repo['Description'],
  114. CreatedAt=repo['CreatedAt'],
  115. GroupId=repo['GroupId'],
  116. GroupName=repo['GroupName']
  117. )
  118. DepotList.append(repo_model)
  119. currentPage += 1
  120. return DepotList
  121. else:
  122. print(f'can not find repo in project {self.project_name}')
  123. except Exception as e:
  124. raise Exception(e)
  125. def get_repo_info(self, repo_name: str):
  126. """get repo list"""
  127. data = {
  128. 'Action': 'DescribeTeamDepotInfoList',
  129. 'ProjectName': self.project_name,
  130. 'DepotName': repo_name,
  131. 'PageNumber': 1,
  132. 'PageSize': 50
  133. }
  134. r = self.sess.post(self.url, json=data)
  135. if r.status_code == 200:
  136. res_data = r.json()
  137. try:
  138. if res_data['Response']["DepotData"]["Page"]["TotalRow"] > 0:
  139. DepotList = res_data['Response']["DepotData"]["Depots"]
  140. depot = Repo(
  141. Id=DepotList[0]['Id'],
  142. Name=DepotList[0]['Name'],
  143. HttpsUrl=DepotList[0]['HttpsUrl'],
  144. ProjectId=DepotList[0]['ProjectId'],
  145. SshUrl=DepotList[0]['SshUrl'],
  146. WebUrl=DepotList[0]['WebUrl'],
  147. ProjectName=DepotList[0]['ProjectName'],
  148. Description=DepotList[0]['Description'],
  149. CreatedAt=DepotList[0]['CreatedAt'],
  150. GroupId=DepotList[0]['GroupId'],
  151. GroupName=DepotList[0]['GroupName']
  152. )
  153. return depot
  154. else:
  155. print(f'can not find repo {repo_name} in project {self.project_name}')
  156. except Exception as e:
  157. raise Exception(f'can not find repo {repo_name} in project {self.project_name}')
  158. def get_project_info(self)->Project:
  159. data = {
  160. "Action": "DescribeCodingProjects",
  161. "ProjectName": self.project_name,
  162. "DepotName": "",
  163. "PageNumber": 1,
  164. "PageSize": 50
  165. }
  166. r = self.sess.post(self.url, json=data)
  167. if r.status_code == 200:
  168. res_data = r.json()
  169. try:
  170. if res_data['Response']["Data"]["TotalCount"] > 0:
  171. ProjectList = res_data['Response']["Data"]["ProjectList"]
  172. projet = Project(
  173. Id=ProjectList[0]['Id'],
  174. Name=ProjectList[0]['Name'],
  175. DisplayName=ProjectList[0]['DisplayName'],
  176. Description=ProjectList[0]['Description'],
  177. TeamOwnerId=ProjectList[0]['TeamOwnerId'],
  178. TeamId=ProjectList[0]['TeamId']
  179. )
  180. return projet
  181. except Exception as e:
  182. print(res_data)
  183. print(e)
  184. def create_repo(self, repo_name: str):
  185. """create a repo"""
  186. # get project id
  187. project = self.get_project_info()
  188. if project is not None:
  189. data = {
  190. "Action": "CreateGitDepot",
  191. "ProjectId": project.Id,
  192. "DepotName": repo_name,
  193. "Shared": self.repo_shared,
  194. "Description": "this is your first depot"
  195. }
  196. r = self.sess.post(self.url, json=data)
  197. if r.status_code == 200:
  198. print(f'create repo {repo_name} success', data,r.json())
  199. return True
  200. else:
  201. return False
  202. def delete(self, repo_name: str):
  203. """delete a repo"""
  204. repo = self.get_repo_info(repo_name=repo_name)
  205. if repo is not None:
  206. data = {
  207. "Action": "DeleteGitDepot",
  208. "DepotId": repo.Id
  209. }
  210. r = self.sess.post(self.url, json=data)
  211. if r.status_code == 200:
  212. print(f'delete repo {repo_name} success', data,r.json())
  213. return True
  214. else:
  215. return False
  216. def pull(self, local_repo_path: str):
  217. ''' pull a repo from remote
  218. Args: local_repo_path: local repo path
  219. '''
  220. if local_repo_path[-1] == os.path.sep:
  221. local_repo_path = local_repo_path[:-1]
  222. repo_name = local_repo_path.split(os.path.sep)[-1]
  223. print(f'pull repo:{self.username}/{repo_name} from coding')
  224. os.chdir(local_repo_path)
  225. try:
  226. os.system('git remote remove origin_coding')
  227. except Exception as e:
  228. pass
  229. os.system(
  230. f'git remote add origin_coding https://{self.username}:{self.token}@e.coding.net/{self.username}/{self.project_name}/{repo_name}.git'
  231. )
  232. result = subprocess.run(
  233. ['git', 'symbolic-ref', '--short', 'HEAD'], capture_output=True, text=True, encoding='utf-8')
  234. current_branch = result.stdout.strip()
  235. os.system(f'git pull origin_coding {current_branch}')
  236. os.system('git remote remove origin_coding')
  237. os.chdir('..')
  238. print('pull success')
  239. def push(self, local_repo_path: str):
  240. ''' push a local repo to remote
  241. Args: local_repo_path: local repo path
  242. '''
  243. # check if remote repo is exist
  244. if local_repo_path[-1] == os.path.sep:
  245. local_repo_path = local_repo_path[:-1]
  246. repo_name = local_repo_path.split(os.path.sep)[-1]
  247. print(f'push repo:{self.username}/{repo_name} to coding')
  248. os.chdir(local_repo_path)
  249. os.system('git remote remove origin_coding')
  250. os.system(
  251. f'git remote add origin_coding https://{self.username}:{self.token}@e.coding.net/{self.username}/{self.project_name}/{repo_name}.git'
  252. )
  253. result = subprocess.run(
  254. ['git', 'symbolic-ref', '--short', 'HEAD'], capture_output=True, text=True, encoding='utf-8')
  255. current_branch = result.stdout.strip()
  256. os.system(f'git pull origin_coding {current_branch}')
  257. os.system(f'git push -u origin_coding {current_branch}')
  258. os.system('git remote remove origin_coding')
  259. os.chdir('..')
  260. print('push success')
  261. def clone(self, repo_path: str):
  262. ''' clone all repo from remote
  263. Args: repo_name: repo name
  264. '''
  265. repos = self.get_repo_list()
  266. for repo in repos:
  267. try:
  268. cmd = f'git clone https://{self.username}:{self.token}@e.coding.net/{self.username}/{self.project_name}/{repo["Name"]}.git {repo_path}/{repo["Name"]}'
  269. # print(cmd)
  270. os.system(cmd)
  271. print(f'clone repo:{repo["Name"]} success')
  272. except Exception as e:
  273. pass
  274. @classmethod
  275. def suitable(cls, extractor: str) -> bool:
  276. """check if this extractor is suitable for this platform"""
  277. if extractor == 'coding':
  278. return True
  279. else:
  280. return False