testapi.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import os, json,hashlib,re
  2. from fastapi import APIRouter, BackgroundTasks
  3. from base_config import path, avatar_url
  4. from git import Repo
  5. from pydantic import BaseModel
  6. from models.gitModels import Users
  7. class RequestBody(BaseModel):
  8. uuid: str
  9. repo_url: str
  10. class CommitHash(BaseModel):
  11. uuid: str
  12. repo_url: str
  13. commit_hash: str
  14. def generate_repo_path(uuid, repo_url):
  15. repo_name = repo_url.split("/")[-1].replace(".git", "")
  16. base_path = os.path.join(path, uuid)
  17. return os.path.join(base_path, repo_name), repo_name
  18. def get_repo(uuid, repo_url):
  19. path, _ = generate_repo_path(uuid, repo_url)
  20. if not os.path.exists(path):
  21. return 0
  22. return Repo(path)
  23. def git_stats_to_json(text):
  24. pattern = r",?\s*(\d+)\s*files changed|,?\s*(\d+)\s*insertions\(\+\)|,?\s*(\d+)\s+deletions\(\-\)"
  25. data = re.findall(pattern, text)
  26. result = {}
  27. for item in data:
  28. if item[0]:
  29. result["files_changed"] = int(item[0])
  30. if item[1]:
  31. result["insertions"] = int(item[1])
  32. if item[2]:
  33. result["deletions"] = int(item[2])
  34. return result
  35. testapi = APIRouter()
  36. import hashlib
  37. from fastapi import APIRouter
  38. from git import Repo, GitCommandError
  39. import json
  40. @testapi.post("/log")
  41. async def log(request: RequestBody):
  42. local_path, _ = generate_repo_path(request.uuid, request.repo_url)
  43. print(local_path)
  44. repo = get_repo(request.uuid, request.repo_url)
  45. if not repo:
  46. return {
  47. "status": "404",
  48. "msg": "仓库不存在",
  49. "uuid": request.uuid,
  50. "repo_url": request.repo_url,
  51. "local_path": local_path
  52. }
  53. # 使用git log --numstat一次性获取所有必要信息
  54. git_log_format = '--pretty=format:%h|%an|%ce|%s|%cd'
  55. try:
  56. log_output = repo.git.log(
  57. git_log_format,
  58. '--numstat',
  59. '--no-renames',
  60. date='format:%Y-%m-%d %H:%M'
  61. )
  62. except GitCommandError as e:
  63. return {"status": "500", "msg": f"获取日志失败: {str(e)}"}
  64. log = []
  65. current_commit = None
  66. for line in log_output.split('\n'):
  67. if not line.strip():
  68. continue # 跳过空行
  69. if '\t' in line and len(line.split('\t')) == 3:
  70. # 处理numstat行,例如 "10\t5\tfile.txt"
  71. if current_commit is None:
  72. continue # 防止数据错误
  73. insertions_str, deletions_str, _ = line.split('\t')
  74. try:
  75. insertions = int(insertions_str) if insertions_str != '-' else 0
  76. deletions = int(deletions_str) if deletions_str != '-' else 0
  77. except ValueError:
  78. insertions, deletions = 0, 0
  79. current_commit['change']['insertions'] += insertions
  80. current_commit['change']['deletions'] += deletions
  81. current_commit['change']['files'] += 1
  82. else:
  83. # 处理提交信息行,例如 "abc123|Author|email|summary|2023-10-01 12:34"
  84. if current_commit is not None:
  85. # 生成avatar的md5
  86. email = current_commit['email']
  87. email_md5 = hashlib.md5(email.encode('utf-8')).hexdigest()
  88. current_commit['avatar'] = f"{avatar_url}{email_md5}?d=identicon"
  89. log.append(current_commit)
  90. try:
  91. commit_hash, author, email, summary, date = line.split('|', 4)
  92. current_commit = {
  93. "commit": commit_hash,
  94. "author": author,
  95. "email": email,
  96. "summary": summary,
  97. "date": date,
  98. "avatar": "",
  99. "change": {
  100. "insertions": 0,
  101. "deletions": 0,
  102. "files": 0
  103. }
  104. }
  105. except ValueError:
  106. current_commit = None # 忽略格式错误行
  107. # 添加最后一个提交
  108. if current_commit is not None:
  109. email = current_commit['email']
  110. email_md5 = hashlib.md5(email.encode('utf-8')).hexdigest()
  111. current_commit['avatar'] = f"{avatar_url}{email_md5}?d=identicon"
  112. log.append(current_commit)
  113. # 按时间倒序排列(git log默认最新在前)
  114. print(log)
  115. return {
  116. "status": "200",
  117. "msg": "成功获取日志",
  118. "uuid": request.uuid,
  119. "repo_url": request.repo_url,
  120. "local_path": local_path,
  121. "git_log": log
  122. }