Browse Source

🎈 perf: 对部分接口进行了优化

Pchen. 2 months ago
parent
commit
aeb4f73c82
2 changed files with 82 additions and 33 deletions
  1. 36 6
      apis/Repos/GetRepoLog.js
  2. 46 27
      apis/Repos/GitContributors.js

+ 36 - 6
apis/Repos/GetRepoLog.js

@@ -43,17 +43,47 @@ class GetRepoLog extends API {
         try {
             const git = simpleGit()
             await git.cwd(r[0].path)
-            const commits = await git.log()
-            
+
+            const rawLogs = await git.raw([
+                "log",
+                "--no-merges",
+                "--pretty=format:%H|%an|%ae|%ad|%s",
+                "--shortstat"
+            ])
+
+            const lines = rawLogs.split("\n")
+            const commits = []
+            let current = null
+
+            for (let i = 0; i < lines.length; i++) {
+                const line = lines[i].trim()
+
+                // 提交信息行
+                if (line.includes("|") && !line.includes("file changed")) {
+                    const [hash, name, email, date, ...messageParts] = line.split("|")
+
+                    current = {
+                        hash,
+                        name,
+                        email,
+                        date, 
+                        message: messageParts.join("|").trim()
+                    }
+
+                    commits.push(current)
+                }
+            }
+
             res.json({
                 ...BaseStdResponse.OK,
                 data: commits
             })
-
-        } catch (error) {
-            this.logger.error('获取仓库历史失败!' + error.stack)
+        } catch (err) {
+            res.json({
+                ...BaseStdResponse.ERR,
+                message: "Git 日志分析失败"
+            });
         }
-
     }
 }
 

+ 46 - 27
apis/Repos/GitContributors.js

@@ -23,52 +23,71 @@ class GitContributors extends API {
         try {
             const git = simpleGit()
             await git.cwd(repoPath)
-
-            // 获取提交日志,包括作者姓名和邮箱
+    
+            // 获取详细日志,带上插入删除统计并排除 merge 提交
             const logs = await git.raw([
                 "log",
-                "--format=%an <%ae>",
+                "--no-merges",
+                "--pretty=format:%H|%an|%ae",
                 "--shortstat"
             ])
-
-            const lines = logs.split("\n").map(l => l.trim()).filter(l => l)
-            let contributors = {}
+    
+            const lines = logs.split("\n")
+            const contributors = {}
             let currentAuthor = null
-            for (const line of lines) {
-                if (line.includes("<") && line.includes(">")) {
-                    const match = line.match(/(.*?) <(.*?)>/)
-                    if (!match) continue
-                    const name = match[1].trim()
-                    const email = match[2].trim()
-                    currentAuthor = name
+    
+            for (let i = 0; i < lines.length; i++) {
+                const line = lines[i].trim()
+    
+                if (line.includes("|")) {
+                    const [commitHash, name, email] = line.split("|")
+                    currentAuthor = email // 用邮箱作为唯一 key 更稳妥
                     if (!contributors[currentAuthor]) {
                         contributors[currentAuthor] = {
                             name,
                             email,
                             avatar: this.getGravatarUrl(email),
                             commits: 0,
-                            linesChanged: 0
+                            linesAdded: 0,
+                            linesDeleted: 0,
+                            filesChanged: 0,
+                            linesChanged: 0 // total changes
                         }
                     }
                     contributors[currentAuthor].commits += 1
-                } else if (line.includes("file changed")) {
-                    const match = line.match(/(\d+) insertions?\(\+\)|(\d+) deletions?\(-\)/g)
-                    if (match) {
-                        const changes = match.map(m => parseInt(m.match(/\d+/)[0], 10)).reduce((a, b) => a + b, 0)
-                        contributors[currentAuthor].linesChanged += changes
+    
+                    // 接下来的 shortstat 统计信息在下一行
+                    const statLine = lines[i + 1]?.trim() || ""
+                    const statMatch = {
+                        filesChanged: statLine.match(/(\d+) file[s]? changed/),
+                        insertions: statLine.match(/(\d+) insertion[s]?\(\+\)/),
+                        deletions: statLine.match(/(\d+) deletion[s]?\(-\)/),
                     }
+    
+                    const files = statMatch.filesChanged ? parseInt(statMatch.filesChanged[1], 10) : 0
+                    const insertions = statMatch.insertions ? parseInt(statMatch.insertions[1], 10) : 0
+                    const deletions = statMatch.deletions ? parseInt(statMatch.deletions[1], 10) : 0
+    
+                    contributors[currentAuthor].filesChanged += files
+                    contributors[currentAuthor].linesAdded += insertions
+                    contributors[currentAuthor].linesDeleted += deletions
+                    contributors[currentAuthor].linesChanged += insertions + deletions
+    
+                    if (statLine) i++ // 跳过 shortstat 行
                 }
             }
-
-            const sortedContributors = Object.values(contributors)
-                .sort((a, b) => b.linesChanged - a.linesChanged || b.commits - a.commits)
-
-            return sortedContributors
-        } catch (error) {
-            console.error("获取仓库开发者失败:", error)
-            throw new Error("获取仓库开发者失败")
+    
+            const sorted = Object.values(contributors).sort(
+                (a, b) => b.linesChanged - a.linesChanged || b.commits - a.commits
+            )
+    
+            return sorted
+        } catch (err) {
+            console.error("分析 Git 贡献者失败:", err)
+            throw new Error("分析 Git 贡献者失败")
         }
     }
+    
 
     async onRequest(req, res) {
         let { uuid, session, id } = req.query