@@ -8,6 +8,70 @@ import { truncateOutput } from "../integrations/misc/extract-text"
88const execAsync = promisify ( exec )
99const SVN_OUTPUT_LINE_LIMIT = 500
1010
11+ // SVN Debug Logger
12+ export class SvnLogger {
13+ private static outputChannel : vscode . OutputChannel | null = null
14+
15+ static getOutputChannel ( ) : vscode . OutputChannel {
16+ if ( ! this . outputChannel ) {
17+ this . outputChannel = vscode . window . createOutputChannel ( "Roo Code - SVN Debug" )
18+ }
19+ return this . outputChannel
20+ }
21+
22+ static debug ( message : string , ...args : any [ ] ) {
23+ const timestamp = new Date ( ) . toISOString ( )
24+ const logMessage = `[${ timestamp } ] [DEBUG] ${ message } `
25+
26+ // Log to console
27+ console . log ( logMessage , ...args )
28+
29+ // Log to VS Code output channel
30+ const channel = this . getOutputChannel ( )
31+ channel . appendLine ( logMessage )
32+ if ( args . length > 0 ) {
33+ channel . appendLine ( ` Args: ${ JSON . stringify ( args , null , 2 ) } ` )
34+ }
35+ }
36+
37+ static error ( message : string , error ?: any ) {
38+ const timestamp = new Date ( ) . toISOString ( )
39+ const logMessage = `[${ timestamp } ] [ERROR] ${ message } `
40+
41+ // Log to console
42+ console . error ( logMessage , error )
43+
44+ // Log to VS Code output channel
45+ const channel = this . getOutputChannel ( )
46+ channel . appendLine ( logMessage )
47+ if ( error ) {
48+ channel . appendLine ( ` Error: ${ error . toString ( ) } ` )
49+ if ( error . stack ) {
50+ channel . appendLine ( ` Stack: ${ error . stack } ` )
51+ }
52+ }
53+ }
54+
55+ static info ( message : string , ...args : any [ ] ) {
56+ const timestamp = new Date ( ) . toISOString ( )
57+ const logMessage = `[${ timestamp } ] [INFO] ${ message } `
58+
59+ // Log to console
60+ console . log ( logMessage , ...args )
61+
62+ // Log to VS Code output channel
63+ const channel = this . getOutputChannel ( )
64+ channel . appendLine ( logMessage )
65+ if ( args . length > 0 ) {
66+ channel . appendLine ( ` Data: ${ JSON . stringify ( args , null , 2 ) } ` )
67+ }
68+ }
69+
70+ static showOutput ( ) {
71+ this . getOutputChannel ( ) . show ( )
72+ }
73+ }
74+
1175export interface SvnRepositoryInfo {
1276 repositoryUrl ?: string
1377 repositoryName ?: string
@@ -27,42 +91,57 @@ export interface SvnCommit {
2791 * @returns SVN repository information or empty object if not an SVN repository
2892 */
2993export async function getSvnRepositoryInfo ( workspaceRoot : string ) : Promise < SvnRepositoryInfo > {
94+ SvnLogger . debug ( "getSvnRepositoryInfo called" , { workspaceRoot } )
95+
3096 try {
3197 const svnDir = path . join ( workspaceRoot , ".svn" )
98+ SvnLogger . debug ( "Checking SVN directory" , { svnDir } )
3299
33100 // Check if .svn directory exists
34101 try {
35102 await fs . access ( svnDir )
36- } catch {
37- // Not an SVN repository
103+ SvnLogger . debug ( "SVN directory found" )
104+ } catch ( error ) {
105+ SvnLogger . debug ( "SVN directory not found - not an SVN repository" , {
106+ error : ( error instanceof Error ? error : new Error ( String ( error ) ) ) . toString ( ) ,
107+ } )
38108 return { }
39109 }
40110
41111 const svnInfo : SvnRepositoryInfo = { }
42112
43113 // Try to get SVN info using svn info command
44114 try {
115+ SvnLogger . debug ( "Executing 'svn info' command" , { cwd : workspaceRoot } )
45116 const { stdout } = await execAsync ( "svn info" , { cwd : workspaceRoot } )
117+ SvnLogger . debug ( "SVN info command output" , { stdout } )
46118
47119 // Parse SVN info output
48120 const urlMatch = stdout . match ( / ^ U R L : \s * ( .+ ) $ / m)
49121 if ( urlMatch && urlMatch [ 1 ] ) {
50122 const url = urlMatch [ 1 ] . trim ( )
51123 svnInfo . repositoryUrl = url
52124 svnInfo . repositoryName = extractSvnRepositoryName ( url )
125+ SvnLogger . debug ( "Extracted repository info" , { url, repositoryName : svnInfo . repositoryName } )
126+ } else {
127+ SvnLogger . debug ( "No URL found in SVN info output" )
53128 }
54129
55130 const rootMatch = stdout . match ( / ^ W o r k i n g C o p y R o o t P a t h : \s * ( .+ ) $ / m)
56131 if ( rootMatch && rootMatch [ 1 ] ) {
57132 svnInfo . workingCopyRoot = rootMatch [ 1 ] . trim ( )
133+ SvnLogger . debug ( "Found working copy root" , { workingCopyRoot : svnInfo . workingCopyRoot } )
134+ } else {
135+ SvnLogger . debug ( "No working copy root found in SVN info output" )
58136 }
59137 } catch ( error ) {
60- // Ignore SVN info errors
138+ SvnLogger . error ( " SVN info command failed" , error instanceof Error ? error : new Error ( String ( error ) ) )
61139 }
62140
141+ SvnLogger . info ( "Final SVN repository info" , svnInfo )
63142 return svnInfo
64143 } catch ( error ) {
65- // Return empty object on any error
144+ SvnLogger . error ( "Error in getSvnRepositoryInfo" , error instanceof Error ? error : new Error ( String ( error ) ) )
66145 return { }
67146 }
68147}
@@ -118,11 +197,18 @@ export async function getWorkspaceSvnInfo(): Promise<SvnRepositoryInfo> {
118197 * @returns True if it's an SVN repository, false otherwise
119198 */
120199export async function checkSvnRepo ( cwd : string ) : Promise < boolean > {
200+ SvnLogger . debug ( "checkSvnRepo called" , { cwd } )
201+
121202 try {
122203 const svnDir = path . join ( cwd , ".svn" )
123204 await fs . access ( svnDir )
205+ SvnLogger . debug ( "SVN repository detected" , { svnDir } )
124206 return true
125- } catch {
207+ } catch ( error ) {
208+ SvnLogger . debug ( "Not an SVN repository" , {
209+ cwd,
210+ error : ( error instanceof Error ? error : new Error ( String ( error ) ) ) . toString ( ) ,
211+ } )
126212 return false
127213 }
128214}
@@ -132,10 +218,17 @@ export async function checkSvnRepo(cwd: string): Promise<boolean> {
132218 * @returns True if SVN is available, false otherwise
133219 */
134220export async function checkSvnInstalled ( ) : Promise < boolean > {
221+ SvnLogger . debug ( "checkSvnInstalled called" )
222+
135223 try {
136- await execAsync ( "svn --version" )
224+ const { stdout } = await execAsync ( "svn --version" )
225+ SvnLogger . debug ( "SVN is installed" , { version : stdout . split ( "\n" ) [ 0 ] } )
137226 return true
138- } catch {
227+ } catch ( error ) {
228+ SvnLogger . error (
229+ "SVN is not installed or not available" ,
230+ error instanceof Error ? error : new Error ( String ( error ) ) ,
231+ )
139232 return false
140233 }
141234}
@@ -146,49 +239,83 @@ export async function checkSvnInstalled(): Promise<boolean> {
146239 * @param cwd The working directory
147240 * @returns Array of matching SVN commits
148241 */
149- export async function searchSvnCommits ( query : string , cwd : string ) : Promise < SvnCommit [ ] > {
242+ export async function searchSvnCommits ( query : string , cwd : string , p0 : number ) : Promise < SvnCommit [ ] > {
243+ SvnLogger . debug ( "searchSvnCommits called" , { query, cwd } )
244+
150245 try {
151246 // Check if SVN is available
152- if ( ! ( await checkSvnInstalled ( ) ) || ! ( await checkSvnRepo ( cwd ) ) ) {
247+ const svnInstalled = await checkSvnInstalled ( )
248+ const isSvnRepo = await checkSvnRepo ( cwd )
249+
250+ SvnLogger . debug ( "SVN availability check" , { svnInstalled, isSvnRepo } )
251+
252+ if ( ! svnInstalled || ! isSvnRepo ) {
253+ SvnLogger . debug ( "SVN not available or not a repository, returning empty array" )
153254 return [ ]
154255 }
155256
156257 const commits : SvnCommit [ ] = [ ]
157258
158259 // If query looks like a revision number, search for that specific revision
159260 if ( / ^ \d + $ / . test ( query ) ) {
261+ SvnLogger . debug ( "Query looks like revision number, searching for specific revision" , { revision : query } )
160262 try {
161- const { stdout } = await execAsync ( `svn log -r ${ query } --xml` , { cwd } )
263+ const command = `svn log -r ${ query } --xml`
264+ SvnLogger . debug ( "Executing revision search command" , { command, cwd } )
265+
266+ const { stdout } = await execAsync ( command , { cwd } )
267+ SvnLogger . debug ( "Revision search output" , { stdout } )
268+
162269 const revisionCommits = parseSvnLogXml ( stdout )
163270 commits . push ( ...revisionCommits )
164- } catch {
165- // Revision might not exist, continue with general search
271+ SvnLogger . debug ( "Found commits for revision" , {
272+ count : revisionCommits . length ,
273+ commits : revisionCommits ,
274+ } )
275+ } catch ( error ) {
276+ SvnLogger . debug ( "Revision search failed, continuing with general search" , {
277+ error : ( error instanceof Error ? error : new Error ( String ( error ) ) ) . toString ( ) ,
278+ } )
166279 }
167280 }
168281
169282 // Search in commit messages (get recent commits and filter)
170283 try {
171- const { stdout } = await execAsync ( "svn log -l 100 --xml" , { cwd } )
284+ const command = "svn log -l 100 --xml"
285+ SvnLogger . debug ( "Executing message search command" , { command, cwd } )
286+
287+ const { stdout } = await execAsync ( command , { cwd } )
288+ SvnLogger . debug ( "Message search output length" , { outputLength : stdout . length } )
289+
172290 const allCommits = parseSvnLogXml ( stdout )
291+ SvnLogger . debug ( "Parsed all commits" , { count : allCommits . length } )
173292
174293 // Filter commits by message content
175294 const messageMatches = allCommits . filter (
176295 ( commit ) => commit . message . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) || commit . revision === query ,
177296 )
297+ SvnLogger . debug ( "Filtered commits by message" , { matchCount : messageMatches . length , query } )
178298
179299 // Add unique commits (avoid duplicates from revision search)
180300 messageMatches . forEach ( ( commit ) => {
181301 if ( ! commits . some ( ( c ) => c . revision === commit . revision ) ) {
182302 commits . push ( commit )
183303 }
184304 } )
185- } catch {
186- // Ignore errors in message search
305+ } catch ( error ) {
306+ SvnLogger . error ( "Message search failed" , error instanceof Error ? error : new Error ( String ( error ) ) )
187307 }
188308
189- return commits . slice ( 0 , 20 ) // Limit results
309+ const finalCommits = commits . slice ( 0 , 20 ) // Limit results
310+ SvnLogger . info ( "Search completed" , {
311+ query,
312+ totalFound : commits . length ,
313+ returned : finalCommits . length ,
314+ commits : finalCommits ,
315+ } )
316+ return finalCommits
190317 } catch ( error ) {
191- console . error ( "Error searching SVN commits: " , error )
318+ SvnLogger . error ( "Error searching SVN commits" , error instanceof Error ? error : new Error ( String ( error ) ) )
192319 return [ ]
193320 }
194321}
0 commit comments