output.txt 5.0 KB

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