gitRouter.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import os, json,hashlib
  2. from fastapi import APIRouter, BackgroundTasks
  3. from git import Repo
  4. from pydantic import BaseModel
  5. from models.gitModels import Users
  6. class RequestBody(BaseModel):
  7. uuid: str
  8. repo_url: str
  9. class CommitHash(BaseModel):
  10. uuid: str
  11. repo_url: str
  12. commit_hash: str
  13. def generate_repo_path(uuid, repo_url):
  14. repo_name = repo_url.split("/")[-1].replace(".git", "")
  15. base_path = os.path.join("C:/Users/32965/repo", uuid)
  16. return os.path.join(base_path, repo_name), repo_name
  17. def get_repo(uuid, repo_url):
  18. path, _ = generate_repo_path(uuid, repo_url)
  19. if not os.path.exists(path):
  20. return 0
  21. return Repo(path)
  22. gitrouter = APIRouter()
  23. @gitrouter.post("/clone")
  24. async def clone(request: RequestBody, background_tasks: BackgroundTasks):
  25. local_path, repo_name = generate_repo_path(request.uuid, request.repo_url)
  26. if os.path.exists(local_path):
  27. return {"status": "400", "msg": "仓库已存在", "uuid": request.uuid, "repo_url": request.repo_url,
  28. "path": local_path}
  29. else:
  30. background_tasks.add_task(Repo.clone_from, request.repo_url, local_path)
  31. response = {"status": "200", "msg": "成功创建克隆任务", "uuid": request.uuid, "repo_name": repo_name,
  32. "local_path": local_path}
  33. return response
  34. @gitrouter.post("/log")
  35. async def log(request: RequestBody):
  36. user=await Users.get(uuid=request.uuid)
  37. email = user.email
  38. # email = "gshn666@qq.com"
  39. email_md5 = hashlib.md5(email.encode(encoding='UTF-8')).hexdigest()
  40. avatar = "https://cravatar.cn/avatar/"+email_md5+"?d=identicon"
  41. local_path, _ = generate_repo_path(request.uuid, request.repo_url)
  42. repo = get_repo(request.uuid, request.repo_url)
  43. if not repo:
  44. return {"status": "404", "msg": "仓库不存在", "uuid": request.uuid, "repo_url": request.repo_url,
  45. "local_path": local_path,"email":email,"avatar":avatar}
  46. log_ = repo.git.log('--pretty={"commit":"%h","author":"%an","summary":"%s","date":"%cd"}', max_count=50,
  47. date='format:%Y-%m-%d %H:%M').split("\n")
  48. log = list(map(json.loads, log_))
  49. response = {"status": "200", "msg": "成功获取日志", "uuid": request.uuid, "repo_url": request.repo_url,
  50. "local_path": local_path, "git_log": log,"email":email,"avatar":avatar}
  51. return response
  52. @gitrouter.post("/status")
  53. async def status(request: RequestBody):
  54. repo = get_repo(request.uuid, request.repo_url)
  55. # 手动获取所有数据
  56. active_branch = repo.active_branch
  57. tracking_branch = active_branch.tracking_branch()
  58. ahead = sum(1 for _ in repo.iter_commits(f"{active_branch}..{tracking_branch}"))
  59. behind = sum(1 for _ in repo.iter_commits(f"{tracking_branch}..{active_branch}"))
  60. conflicts = repo.index.unmerged_blobs()
  61. conflicted = [path for path, entries in conflicts.items()]
  62. created_files = repo.untracked_files
  63. current = repo.active_branch.name
  64. head_commit = repo.head.commit
  65. tree = head_commit.tree
  66. all_files = [item.path for item in tree.traverse() if item.type == 'blob']
  67. diffs = repo.index.diff(None)
  68. deleted = [d.a_path for d in diffs if d.change_type == 'D']
  69. detached = repo.head.is_detached
  70. ignored_files = repo.git.execute(["git", "ls-files", "--others", "--ignored", "--exclude-standard"]).split("\n")
  71. modified_files = [d.a_path for d in diffs]
  72. untracked_files = repo.untracked_files
  73. staged_entries = repo.index.entries
  74. staged = [path[0] for path, _ in staged_entries.items()]
  75. tracking = active_branch.tracking_branch().name
  76. status = {"ahead": ahead, "behind": behind, "conflicted": conflicted, "created": created_files,
  77. "current": current, "deleted": deleted, "detached": detached, "files": all_files,
  78. "ignored": ignored_files,
  79. "modified": modified_files, "not_added": untracked_files, "staged": staged, "tracking": tracking}
  80. return status
  81. @gitrouter.post("/change")
  82. async def change(request: CommitHash):
  83. repo = get_repo(request.uuid, request.repo_url)
  84. if not repo:
  85. return {"status": "404", "msg": "仓库不存在", "uuid": request.uuid, "repo_url": request.repo_url}
  86. commit = repo.commit(request.commit_hash)
  87. if not commit.parents: # 处理首次提交
  88. print("首次提交,无父提交对比")
  89. return
  90. parent = commit.parents[0]
  91. diffs = parent.diff(commit,create_patch=True, no_renames=True)
  92. for diff in diffs:
  93. print(f"文件 {diff.a_path} ({diff.change_type}):")
  94. print(diff.diff.decode('utf-8'))