123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- 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
|