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