Skip to content

Commit 9497c21

Browse files
fix(svn): Unify the SVN revision number format to the 'r' prefix and improve the resolution of submission information
- Fix SVN revision number matching logic and use the 'r' prefix format in a unified way - Improve SVN submission information analysis, correctly handle Chinese encoding and change paths - Add change files and differences information to submission details display
1 parent 5b860fe commit 9497c21

File tree

3 files changed

+123
-27
lines changed

3 files changed

+123
-27
lines changed

src/core/mentions/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export async function parseMentions(
103103
return `Working directory changes (see below for details)`
104104
} else if (/^[a-f0-9]{7,40}$/.test(mention)) {
105105
return `Git commit '${mention}' (see below for commit info)`
106-
} else if (enableSvnContext && /^r?\d+$/.test(mention)) {
106+
} else if (enableSvnContext && /^r\d+$/.test(mention)) {
107107
return `SVN revision '${mention}' (see below for commit info)`
108108
} else if (mention === "terminal") {
109109
return `Terminal Output (see below for output)`
@@ -215,7 +215,7 @@ export async function parseMentions(
215215
} catch (error) {
216216
parsedText += `\n\n<git_commit hash="${mention}">\nError fetching commit info: ${error.message}\n</git_commit>`
217217
}
218-
} else if (enableSvnContext && /^r?\d+$/.test(mention)) {
218+
} else if (enableSvnContext && /^r\d+$/.test(mention)) {
219219
try {
220220
const commitInfo = await getSvnCommitInfoForMentions(mention, cwd)
221221
parsedText += `\n\n<svn_commit revision="${mention}">\n${commitInfo}\n</svn_commit>`

src/utils/svn.ts

Lines changed: 118 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,17 @@ export async function searchSvnCommits(query: string, cwd: string): Promise<SvnC
466466

467467
const commits: SvnCommit[] = []
468468

469-
// If query looks like a revision number, search for that specific revision
470-
if (/^\d+$/.test(query)) {
471-
SvnLogger.debug("Query looks like revision number, searching for specific revision", { revision: query })
469+
// If query looks like a revision number with 'r' prefix, search for that specific revision
470+
// Only support "r123" format, not pure numbers
471+
const revisionMatch = query.match(/^r(\d+)$/i)
472+
if (revisionMatch) {
473+
const revisionNumber = revisionMatch[1]
474+
SvnLogger.debug("Query looks like revision number, searching for specific revision", {
475+
originalQuery: query,
476+
revision: revisionNumber,
477+
})
472478
try {
473-
const command = `svn log -r ${query} --xml`
479+
const command = `svn log -r ${revisionNumber} --xml`
474480
SvnLogger.debug("Executing revision search command", { command, cwd })
475481

476482
const { stdout } = await execAsync(command, { cwd })
@@ -502,10 +508,21 @@ export async function searchSvnCommits(query: string, cwd: string): Promise<SvnC
502508
const allCommits = parseSvnLogXml(stdout)
503509
SvnLogger.debug("Parsed all commits", { count: allCommits.length })
504510

505-
// Filter commits by message content
506-
const messageMatches = allCommits.filter(
507-
(commit) => commit.message.toLowerCase().includes(query.toLowerCase()) || commit.revision === query,
508-
)
511+
// Filter commits by message content or revision match
512+
const messageMatches = allCommits.filter((commit) => {
513+
// Check message content match
514+
const messageMatch = commit.message.toLowerCase().includes(query.toLowerCase())
515+
516+
// Check revision match (only handle "r123" format, not pure numbers)
517+
let revisionMatch = false
518+
const revisionMatchResult = query.match(/^r(\d+)$/i)
519+
if (revisionMatchResult) {
520+
const queryRevision = revisionMatchResult[1]
521+
revisionMatch = commit.revision === queryRevision
522+
}
523+
524+
return messageMatch || revisionMatch
525+
})
509526
SvnLogger.debug("Filtered commits by message", { matchCount: messageMatches.length, query })
510527

511528
// Add unique commits (avoid duplicates from revision search)
@@ -735,29 +752,108 @@ export async function getSvnCommitInfoForMentions(revision: string, cwd: string)
735752
}
736753
console.log("[DEBUG] Clean revision:", cleanRevision)
737754

738-
const { stdout } = await execAsync(`svn log -r ${cleanRevision} -v`, { cwd })
755+
// Use UTF-8 encoding to handle Chinese characters properly
756+
const { stdout } = await execAsync(`svn log -r ${cleanRevision} -v`, {
757+
cwd,
758+
encoding: "utf8",
759+
})
739760
console.log("[DEBUG] SVN log output:", stdout)
740761

762+
// Parse the log output more carefully
741763
const lines = stdout.split("\n")
742-
const logEntry = lines.find((line) => line.includes("r" + cleanRevision))
743-
if (!logEntry) {
764+
765+
// Find the header line (contains revision info)
766+
const headerLineIndex = lines.findIndex((line) => line.includes(`r${cleanRevision} |`))
767+
if (headerLineIndex === -1) {
744768
return `Revision ${revision} not found`
745769
}
746770

747-
const parts = logEntry.split("|").map((part) => part.trim())
748-
if (parts.length >= 4) {
749-
const [rev, author, date] = parts
750-
const messageStart = stdout.indexOf("\n\n")
751-
const messageEnd = stdout.indexOf("\n---", messageStart)
752-
const message =
753-
messageStart !== -1 && messageEnd !== -1
754-
? stdout.substring(messageStart + 2, messageEnd).trim()
755-
: "No message"
771+
const headerLine = lines[headerLineIndex]
772+
const parts = headerLine.split("|").map((part) => part.trim())
756773

757-
return `${rev} by ${author} on ${date}\n${message}`
774+
if (parts.length < 3) {
775+
return `Revision ${revision}: Unable to parse commit information`
758776
}
759777

760-
return `Revision ${revision}: Unable to parse commit information`
778+
const [rev, author, dateInfo] = parts
779+
// Extract just the date part, ignore the Chinese day name to avoid encoding issues
780+
const dateMatch = dateInfo.match(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4})/)
781+
const date = dateMatch ? dateMatch[1] : dateInfo.split("(")[0].trim()
782+
783+
// Find the commit message (after "Changed paths:" section)
784+
let message = "No message"
785+
let changedPaths = ""
786+
787+
// Look for "Changed paths:" section
788+
const changedPathsIndex = lines.findIndex((line) => line.includes("Changed paths:"))
789+
if (changedPathsIndex !== -1) {
790+
// Extract changed paths
791+
const pathLines = []
792+
for (let i = changedPathsIndex + 1; i < lines.length; i++) {
793+
const line = lines[i]
794+
if (line.trim() === "" || line.startsWith("---")) {
795+
break
796+
}
797+
if (line.trim().match(/^[AMDRC]\s+\//)) {
798+
pathLines.push(line.trim())
799+
}
800+
}
801+
changedPaths = pathLines.join("\n")
802+
803+
// Find message after the changed paths section
804+
for (let i = changedPathsIndex + 1; i < lines.length; i++) {
805+
const line = lines[i]
806+
if (line.trim() === "" && i + 1 < lines.length) {
807+
// Check if next line is not a separator and not empty
808+
const nextLine = lines[i + 1]
809+
if (nextLine && !nextLine.startsWith("---") && nextLine.trim() !== "") {
810+
// Found the message
811+
const messageLines = []
812+
for (let j = i + 1; j < lines.length; j++) {
813+
const msgLine = lines[j]
814+
if (msgLine.startsWith("---")) {
815+
break
816+
}
817+
if (msgLine.trim() !== "") {
818+
messageLines.push(msgLine)
819+
}
820+
}
821+
if (messageLines.length > 0) {
822+
message = messageLines.join("\n").trim()
823+
}
824+
break
825+
}
826+
}
827+
}
828+
}
829+
830+
// Get diff information (same as getSvnCommitInfo function)
831+
let diff = ""
832+
try {
833+
console.log("[DEBUG] Getting diff for revision:", cleanRevision)
834+
const { stdout: diffOutput } = await execAsync(`svn diff -c ${cleanRevision}`, {
835+
cwd,
836+
encoding: "utf8",
837+
})
838+
diff = truncateOutput(diffOutput, SVN_OUTPUT_LINE_LIMIT)
839+
console.log("[DEBUG] Diff length:", diff.length)
840+
} catch (error) {
841+
const svnError = error instanceof Error ? error : new Error(String(error))
842+
console.log("[DEBUG] Diff not available for revision:", svnError.message)
843+
}
844+
845+
// Format the result with changed files and diff
846+
let result = `${rev} by ${author} on ${date}\n${message}`
847+
848+
if (changedPaths) {
849+
result += `\n\nChanged files:\n${changedPaths}`
850+
}
851+
852+
if (diff && diff.trim()) {
853+
result += `\n\nDiff:\n${diff}`
854+
}
855+
856+
return result
761857
} catch (error) {
762858
const svnError = error instanceof Error ? error : new Error(String(error))
763859
console.error("[DEBUG] Error getting SVN commit info for mentions:", svnError)

webview-ui/src/components/chat/ChatTextArea.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
158158
} else if (message.type === "svnCommitSearchResults") {
159159
const commits = message.svnCommits.map((commit: any) => ({
160160
type: ContextMenuOptionType.Svn,
161-
value: commit.revision,
161+
value: `r${commit.revision}`,
162162
label: commit.message,
163163
description: `r${commit.revision} by ${commit.author} on ${commit.date}`,
164164
icon: "$(git-commit)",
@@ -213,9 +213,9 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
213213
}
214214
}, [selectedType, searchQuery])
215215

216-
// Fetch SVN commits when SVN is selected or when typing a revision number.
216+
// Fetch SVN commits when SVN is selected or when typing a revision number with 'r' prefix.
217217
useEffect(() => {
218-
if (selectedType === ContextMenuOptionType.Svn || /^r?\d+$/i.test(searchQuery)) {
218+
if (selectedType === ContextMenuOptionType.Svn || /^r\d+$/i.test(searchQuery)) {
219219
const message: WebviewMessage = {
220220
type: "searchSvnCommits",
221221
query: searchQuery || "",

0 commit comments

Comments
 (0)