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	
