Skip to content

Commit 3124968

Browse files
feat(svn): 添加对SVN版本号提及的支持
- 在提及解析中增加对SVN版本号的支持 - 添加获取SVN提交信息的工具函数 - 修改提及正则表达式以匹配SVN版本号 - 为SVN提及添加类型定义和格式化函数
1 parent 15bcf77 commit 3124968

File tree

4 files changed

+149
-5
lines changed

4 files changed

+149
-5
lines changed

src/activate/registerCommands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
257257

258258
// 搜索最近的提交
259259
SvnLogger.info("Searching for recent commits...")
260-
const commits = await searchSvnCommits("", workspaceRoot, 5)
260+
const commits = await searchSvnCommits("", workspaceRoot)
261261
SvnLogger.info(`Found ${commits.length} commits`)
262262
commits.forEach((commit, index) => {
263263
SvnLogger.info(`Commit ${index + 1}: r${commit.revision} - ${commit.message}`)

src/core/mentions/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { isBinaryFile } from "isbinaryfile"
77
import { mentionRegexGlobal, unescapeSpaces } from "../../shared/context-mentions"
88

99
import { getCommitInfo, getWorkingState } from "../../utils/git"
10-
import { getSvnWorkingState } from "../../utils/svn"
10+
import { getSvnWorkingState, getSvnCommitInfoForMentions } from "../../utils/svn"
1111
import { getWorkspacePath } from "../../utils/path"
1212

1313
import { openFile } from "../../integrations/misc/open-file"
@@ -100,6 +100,8 @@ export async function parseMentions(
100100
return `Working directory changes (see below for details)`
101101
} else if (/^[a-f0-9]{7,40}$/.test(mention)) {
102102
return `Git commit '${mention}' (see below for commit info)`
103+
} else if (/^r?\d+$/.test(mention)) {
104+
return `SVN revision '${mention}' (see below for commit info)`
103105
} else if (mention === "terminal") {
104106
return `Terminal Output (see below for output)`
105107
}
@@ -210,6 +212,13 @@ export async function parseMentions(
210212
} catch (error) {
211213
parsedText += `\n\n<git_commit hash="${mention}">\nError fetching commit info: ${error.message}\n</git_commit>`
212214
}
215+
} else if (/^r?\d+$/.test(mention)) {
216+
try {
217+
const commitInfo = await getSvnCommitInfoForMentions(mention, cwd)
218+
parsedText += `\n\n<svn_commit revision="${mention}">\n${commitInfo}\n</svn_commit>`
219+
} catch (error) {
220+
parsedText += `\n\n<svn_commit revision="${mention}">\nError fetching commit info: ${error.message}\n</svn_commit>`
221+
}
213222
} else if (mention === "terminal") {
214223
try {
215224
const terminalOutput = await getLatestTerminalOutput()

src/shared/context-mentions.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ Mention regex:
5555
5656
*/
5757
export const mentionRegex =
58-
/(?<!\\)@((?:\/|\w+:\/\/)(?:[^\s\\]|\\ )+?|[a-f0-9]{7,40}\b|problems\b|git-changes\b|svn-changes\b|terminal\b)(?=[.,;:!?]?(?=[\s\r\n]|$))/
58+
/(?<!\\)@((?:\/|\w+:\/\/)(?:[^\s\\]|\\ )+?|[a-f0-9]{7,40}\b|r?\d+\b|problems\b|git-changes\b|svn-changes\b|terminal\b)(?=[.,;:!?]?(?=[\s\r\n]|$))/
5959
export const mentionRegexGlobal = new RegExp(mentionRegex.source, "g")
6060

6161
export interface MentionSuggestion {
62-
type: "file" | "folder" | "git" | "problems"
62+
type: "file" | "folder" | "git" | "svn" | "problems"
6363
label: string
6464
description?: string
6565
value: string
@@ -75,6 +75,15 @@ export interface GitMentionSuggestion extends MentionSuggestion {
7575
date: string
7676
}
7777

78+
export interface SvnMentionSuggestion extends MentionSuggestion {
79+
type: "svn"
80+
revision: string
81+
shortRevision: string
82+
message: string
83+
author: string
84+
date: string
85+
}
86+
7887
export function formatGitSuggestion(commit: {
7988
hash: string
8089
shortHash: string
@@ -96,6 +105,27 @@ export function formatGitSuggestion(commit: {
96105
}
97106
}
98107

108+
export function formatSvnSuggestion(commit: {
109+
revision: string
110+
shortRevision: string
111+
message: string
112+
author: string
113+
date: string
114+
}): SvnMentionSuggestion {
115+
return {
116+
type: "svn",
117+
label: commit.message,
118+
description: `${commit.shortRevision} by ${commit.author} on ${commit.date}`,
119+
value: commit.revision,
120+
icon: "$(git-commit)", // Using git commit icon for consistency
121+
revision: commit.revision,
122+
shortRevision: commit.shortRevision,
123+
message: commit.message,
124+
author: commit.author,
125+
date: commit.date,
126+
}
127+
}
128+
99129
// Helper function to unescape paths with backslash-escaped spaces
100130
export function unescapeSpaces(path: string): string {
101131
return path.replace(/\\ /g, " ")

src/utils/svn.ts

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ export async function checkSvnInstalled(): Promise<boolean> {
239239
* @param cwd The working directory
240240
* @returns Array of matching SVN commits
241241
*/
242-
export async function searchSvnCommits(query: string, cwd: string, p0: number): Promise<SvnCommit[]> {
242+
export async function searchSvnCommits(query: string, cwd: string): Promise<SvnCommit[]> {
243243
SvnLogger.debug("searchSvnCommits called", { query, cwd })
244244

245245
try {
@@ -499,3 +499,108 @@ export async function getSvnWorkingState(cwd: string): Promise<{
499499
return { status: "", diff: "" }
500500
}
501501
}
502+
503+
/**
504+
* Gets formatted SVN commit information for mentions
505+
* @param revision The revision number (can be with or without 'r' prefix)
506+
* @param cwd The working directory
507+
* @returns Formatted commit information string
508+
*/
509+
export async function getSvnCommitInfoForMentions(revision: string, cwd: string): Promise<string> {
510+
try {
511+
console.log("[DEBUG] getSvnCommitInfoForMentions called with revision:", revision, "cwd:", cwd)
512+
513+
if (!(await checkSvnInstalled()) || !(await checkSvnRepo(cwd))) {
514+
console.log("[DEBUG] SVN not installed or not a repository")
515+
return "Error: SVN not available or not an SVN repository"
516+
}
517+
518+
// Clean revision number (remove 'r' prefix if present)
519+
const cleanRevision = revision.replace(/^r/i, "")
520+
console.log("[DEBUG] Clean revision:", cleanRevision)
521+
522+
// Get commit info
523+
const { stdout: logOutput } = await execAsync(`svn log -r ${cleanRevision} -v`, { cwd })
524+
console.log("[DEBUG] SVN log output:", logOutput)
525+
526+
// Parse the log output
527+
const lines = logOutput.split("\n")
528+
let commitInfo = ""
529+
let author = ""
530+
let date = ""
531+
let message = ""
532+
let changedPaths = ""
533+
534+
// Find the revision line
535+
const revisionLineIndex = lines.findIndex((line) => line.includes(`r${cleanRevision}`))
536+
if (revisionLineIndex >= 0) {
537+
const revisionLine = lines[revisionLineIndex]
538+
const match = revisionLine.match(/r(\d+)\s+\|\s+([^|]+)\s+\|\s+([^|]+)\s+\|/)
539+
if (match) {
540+
author = match[2].trim()
541+
date = match[3].trim()
542+
}
543+
}
544+
545+
// Find changed paths
546+
const changedPathsStart = lines.findIndex((line) => line.includes("Changed paths:"))
547+
if (changedPathsStart >= 0) {
548+
let i = changedPathsStart + 1
549+
const pathLines = []
550+
while (i < lines.length && lines[i].trim() && !lines[i].startsWith("-")) {
551+
if (lines[i].trim()) {
552+
pathLines.push(lines[i].trim())
553+
}
554+
i++
555+
}
556+
changedPaths = pathLines.join("\n")
557+
}
558+
559+
// Find message
560+
const messageStart = lines.findIndex(
561+
(line, index) =>
562+
index > revisionLineIndex && line.trim() && !line.startsWith("-") && !line.includes("Changed paths:"),
563+
)
564+
if (messageStart >= 0) {
565+
let i = messageStart
566+
const messageLines = []
567+
while (i < lines.length && !lines[i].startsWith("-")) {
568+
if (lines[i].trim()) {
569+
messageLines.push(lines[i].trim())
570+
}
571+
i++
572+
}
573+
message = messageLines.join("\n")
574+
}
575+
576+
// Get diff
577+
let diff = ""
578+
try {
579+
const { stdout: diffOutput } = await execAsync(`svn diff -c ${cleanRevision}`, { cwd })
580+
diff = truncateOutput(diffOutput, SVN_OUTPUT_LINE_LIMIT)
581+
} catch (error) {
582+
console.log("[DEBUG] SVN diff command failed:", error)
583+
diff = "Diff not available"
584+
}
585+
586+
// Format the output
587+
commitInfo = `Revision: r${cleanRevision}\n`
588+
commitInfo += `Author: ${author}\n`
589+
commitInfo += `Date: ${date}\n\n`
590+
commitInfo += `Message: ${message}\n\n`
591+
592+
if (changedPaths) {
593+
commitInfo += `Changed Paths:\n${changedPaths}\n\n`
594+
}
595+
596+
if (diff && diff.trim()) {
597+
commitInfo += `Full Changes:\n\n${diff}`
598+
}
599+
600+
console.log("[DEBUG] Formatted commit info:", commitInfo)
601+
return commitInfo
602+
} catch (error) {
603+
console.error("[DEBUG] Error getting SVN commit info for mentions:", error)
604+
return `Error fetching SVN commit r${revision}: ${error.message}`
605+
}
606+
}

0 commit comments

Comments
 (0)