fulian23 4 months ago
commit
450e2669d8

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 45 - 0
.idea/CopilotChatHistory.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CopilotChatHistory">
+    <option name="conversations">
+      <list>
+        <Conversation>
+          <option name="createTime" value="1742477344649" />
+          <option name="id" value="0195b3be3f897f5799057ce28aacd1ef" />
+          <option name="title" value="新对话 2025年3月20日 21:29:04" />
+          <option name="updateTime" value="1742477344649" />
+        </Conversation>
+        <Conversation>
+          <option name="createTime" value="1742466058549" />
+          <option name="id" value="0195b3120935765ca075fe467ac73da5" />
+          <option name="title" value="新对话 2025年3月20日 18:20:58" />
+          <option name="updateTime" value="1742466058549" />
+        </Conversation>
+        <Conversation>
+          <option name="createTime" value="1742390504729" />
+          <option name="id" value="0195ae912d197868ab44335846c122f6" />
+          <option name="title" value="新对话 2025年3月19日 21:21:44" />
+          <option name="updateTime" value="1742390504729" />
+        </Conversation>
+        <Conversation>
+          <option name="createTime" value="1742382368179" />
+          <option name="id" value="0195ae1505b37b5faf8e0d8fb5c30336" />
+          <option name="title" value="新对话 2025年3月19日 19:06:08" />
+          <option name="updateTime" value="1742382368179" />
+        </Conversation>
+        <Conversation>
+          <option name="createTime" value="1742376286697" />
+          <option name="id" value="0195adb839e971648c198471283307dc" />
+          <option name="title" value="新对话 2025年3月19日 17:24:46" />
+          <option name="updateTime" value="1742376286697" />
+        </Conversation>
+        <Conversation>
+          <option name="createTime" value="1742363604602" />
+          <option name="id" value="0195acf6b67a7859bf046bc3abaf64bd" />
+          <option name="title" value="新对话 2025年3月19日 13:53:24" />
+          <option name="updateTime" value="1742363604602" />
+        </Conversation>
+      </list>
+    </option>
+  </component>
+</project>

+ 10 - 0
.idea/GitNexus.iml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.venv" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 13 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,13 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="LossyEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoredIdentifiers">
+        <list>
+          <option value="FastApi.api.gitRouter.models" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>

+ 6 - 0
.idea/inspectionProfiles/profiles_settings.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>

+ 7 - 0
.idea/misc.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Black">
+    <option name="sdkName" value="Python 3.12 (GitNexus)" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (GitNexus)" project-jdk-type="Python SDK" />
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/GitNexus.iml" filepath="$PROJECT_DIR$/.idea/GitNexus.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

BIN
api/__pycache__/gitRouter.cpython-312.pyc


+ 81 - 0
api/gitRouter.py

@@ -0,0 +1,81 @@
+import os,json
+from fastapi import APIRouter,BackgroundTasks
+from models.gitModels import *
+
+from git import Repo
+
+from pydantic import BaseModel
+
+class RequestBody(BaseModel):
+    uuid: str
+    repo_url: str
+
+
+def generate_repo_path(uuid, repo_url):
+    repo_name = repo_url.split("/")[-1].replace(".git", "")
+    base_path = os.path.join("C:/Users/32965/repo", uuid)
+    return os.path.join(base_path, repo_name), repo_name
+
+
+def get_repo(uuid, repo_url):
+    path, _ = generate_repo_path(uuid, repo_url)
+    if not os.path.exists(path):
+        return 0
+    return Repo(path)
+
+gitrouter=APIRouter()
+
+@gitrouter.post("/clone")
+async def clone(request: RequestBody, background_tasks: BackgroundTasks):
+    local_path, repo_name = generate_repo_path(request.uuid, request.repo_url)
+    if os.path.exists(local_path):
+        return {"status": "400", "msg": "仓库已存在", "uuid": request.uuid, "repo_url": request.repo_url, "path": local_path}
+    else:
+        background_tasks.add_task(Repo.clone_from, request.repo_url, local_path)
+        response= {"status":"200","msg": "成功创建克隆任务","uuid":request.uuid,"repoName":repo_name,"local_path":local_path}
+        return response
+
+@gitrouter.post("/log")
+async def log(request: RequestBody):
+    local_path, _ = generate_repo_path(request.uuid, request.repo_url)
+    repo=get_repo(request.uuid,request.repo_url)
+    if not repo:
+        return {"status": "400", "msg": "仓库不存在", "uuid": request.uuid, "repo_url": request.repo_url,
+                "local_path": local_path}
+
+    log_=repo.git.log('--pretty={"commit":"%h","author":"%an","summary":"%s","date":"%cd"}', max_count=50,
+                          date='format:%Y-%m-%d %H:%M').split("\n")
+    log=list(map(json.loads, log_))
+    response= {"status":"200","msg": "成功获取日志","uuid":request.uuid,"repo_url":request.repo_url,
+               "local_path":local_path,"git_log":log}
+    return response
+
+@gitrouter.post("/status")
+async def status(request: RequestBody):
+    repo=get_repo(request.uuid,request.repo_url)
+    # 手动获取所有数据
+    active_branch = repo.active_branch
+    tracking_branch = active_branch.tracking_branch()
+    ahead = sum(1 for _ in repo.iter_commits(f"{active_branch}..{tracking_branch}"))
+    behind = sum(1 for _ in repo.iter_commits(f"{tracking_branch}..{active_branch}"))
+    conflicts = repo.index.unmerged_blobs()
+    conflicted = [path for path, entries in conflicts.items()]
+    created_files = repo.untracked_files
+    current = repo.active_branch.name
+    head_commit = repo.head.commit
+    tree = head_commit.tree
+    all_files = [item.path for item in tree.traverse() if item.type == 'blob']
+    diffs = repo.index.diff(None)
+    deleted = [d.a_path for d in diffs if d.change_type == 'D']
+    detached = repo.head.is_detached
+    ignored_files = repo.git.execute(["git", "ls-files", "--others", "--ignored", "--exclude-standard"]).split("\n")
+    modified_files = [d.a_path for d in diffs]
+    untracked_files = repo.untracked_files
+    staged_entries = repo.index.entries
+    staged = [path[0] for path, _ in staged_entries.items()]
+    tracking = active_branch.tracking_branch().name
+
+    status = {"ahead": ahead, "behind": behind, "conflicted": conflicted, "created": created_files,
+              "current": current,"deleted": deleted, "detached": detached, "files": all_files, "ignored": ignored_files,
+              "modified": modified_files,"not_added": untracked_files, "staged": staged, "tracking": tracking}
+    return status

+ 25 - 0
db_config.py

@@ -0,0 +1,25 @@
+TORTOISE_ORM = {
+    "connections": {
+        "default": {
+            "engine": "tortoise.backends.mysql",
+            "credentials": {
+                "host": "8.137.37.202",
+                "port": 3306,
+                "user": "gitnexus",
+                "password": "Yx3ud937",
+                "database": "gitnexus",
+                "minsize": 3,    # 最小连接数
+                "maxsize": 20,   # 最大连接数
+                "charset": "utf8mb4"
+            }
+        }
+    },
+    "apps": {
+        "models": {
+            "models": ["models.gitModels"],  # 包含模型文件
+            "default_connection": "default"
+        }
+    },
+    "use_tz": False,
+    "timezone": "Asia/Shanghai"
+}

+ 23 - 0
demo.py

@@ -0,0 +1,23 @@
+from fastapi_cdn_host import monkey_patch_for_docs_ui
+from fastapi import FastAPI
+from uvicorn import run
+from models.gitModels import *
+
+from api.gitRouter import gitrouter
+
+from tortoise.contrib.fastapi import register_tortoise
+from db_config import TORTOISE_ORM
+
+app = FastAPI()
+monkey_patch_for_docs_ui(app)
+register_tortoise(app=app, config=TORTOISE_ORM)
+
+@app.get("/user/{id}")
+async def test(id: int):
+    user= await Users.get(id=id)
+    print(type(user))
+    return user
+app.include_router(gitrouter,prefix="/git")
+
+if __name__ == "__main__":
+    run(app,host="127.0.0.1",port=8000)

+ 82 - 0
gittest.py

@@ -0,0 +1,82 @@
+from git import Repo
+import os
+
+# 配置参数
+repo_url_https = "https://github.com/fulian23/Maxtool"  # HTTPS克隆地址
+repo_url_ssh = "git@github.com:fulian23/Maxtool.git"  # SSH推送地址
+local_path = r"C:\Users\32965\Maxtool"  # 本地存储路径
+ssh_key_path = r"C:\Users\32965\.ssh\id_rsa"  # SSH私钥路径
+
+# 1. 克隆仓库(使用HTTPS)
+# Repo.clone_from(repo_url_https, local_path)
+
+# # 2. 修改远程仓库地址为SSH格式
+# repo = Repo(local_path)
+# origin = repo.remotes.origin
+# origin.set_url(repo_url_ssh)
+#
+# # 3. 创建测试文件
+# test_file = os.path.join(local_path, "test.txt")
+# with open(test_file, "w") as f:
+#     f.write("This is a test file added via GitPython")
+#
+# # 4. 提交更改
+# repo.git.add("test.txt")
+# repo.git.commit("-m", "Add test file")
+#
+# # 5. 配置SSH密钥并推送
+# ssh_cmd = f"ssh -i {ssh_key_path}"
+# with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd):
+#     origin.push()
+
+# local_path = os.path.join('test', 't1')
+from git import Repo
+
+repo = Repo("../9992cddb-b7d1-99ec-1bd2-35fdc177e623/test")
+# branches = repo.remote().refs
+# for item in branches:
+#     print(item.remote_head)
+
+
+# 1. 基础状态
+
+
+# 2. 本地与远程差异
+active_branch = repo.active_branch
+tracking_branch = active_branch.tracking_branch()
+ahead = sum(1 for _ in repo.iter_commits(f"{active_branch}..{tracking_branch}"))
+behind = sum(1 for _ in repo.iter_commits(f"{tracking_branch}..{active_branch}"))
+
+conflicts = repo.index.unmerged_blobs()
+
+conflicted = [path for path, entries in conflicts.items()]
+
+created_files = repo.untracked_files
+current = repo.active_branch.name
+
+head_commit = repo.head.commit
+tree = head_commit.tree
+all_files = [item.path for item in tree.traverse() if item.type == 'blob']
+
+diffs = repo.index.diff(None)
+deleted = [d.a_path for d in diffs if d.change_type == 'D']
+
+detached = repo.head.is_detached
+
+ignored_files = repo.git.execute(["git", "ls-files", "--others", "--ignored", "--exclude-standard"]).split("\n")
+
+modified_files = [d.a_path for d in diffs]
+
+untracked_files = repo.untracked_files
+
+staged_entries = repo.index.entries
+staged = [path[0] for path, _ in staged_entries.items()]
+
+tracking = active_branch.tracking_branch().name
+
+status = {"ahead": ahead, "behind": behind, "condlicted": conflicted, "created": created_files,
+          "current": current,
+          "deleted": deleted, "detached": detached, "files": all_files, "ignored": ignored_files,
+          "modified": modified_files,
+          "not_added": untracked_files, "staged": staged, "tracking": tracking}
+print(status)

+ 0 - 0
gittt.py


+ 2 - 0
models/AIModels.py

@@ -0,0 +1,2 @@
+from tortoise.models import Model
+from tortoise import fields

+ 0 - 0
models/__init__.py


BIN
models/__pycache__/__init__.cpython-312.pyc


BIN
models/__pycache__/gitModels.cpython-312.pyc


+ 11 - 0
models/gitModels.py

@@ -0,0 +1,11 @@
+from tortoise.models import Model
+from tortoise import fields
+
+class Users(Model):
+    id = fields.IntField(pk=True)
+    uuid = fields.UUIDField(unique=True)
+    username = fields.CharField(max_length=50, unique=True, index=True)
+    session = fields.CharField(max_length=50, unique=True)
+    password = fields.CharField(max_length=50)
+    permission = fields.JSONField()
+    git_info = fields.JSONField()