svn_log
Retrieve commit history from a Subversion (SVN) repository by specifying a path, revision range, or maximum entries to streamline repository management and version tracking.
Instructions
Ver historial de commits del repositorio
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Número máximo de entradas | |
| path | No | Ruta específica | |
| revision | No | Revisión específica o rango (ej: 100:200) |
Implementation Reference
- tools/svn-service.ts:203-285 (handler)Main handler for 'svn_log' tool. Builds 'svn log' command with optional path, limit, revision. Executes command, parses output using parseLogOutput helper, returns structured SvnLogEntry[] or handles specific SVN errors./** * Obtener historial de cambios (log) */ async getLog( path?: string, limit?: number, revision?: string ): Promise<SvnResponse<SvnLogEntry[]>> { try { const args = ['log']; if (limit && limit > 0) { args.push('--limit', limit.toString()); } if (revision) { args.push('--revision', revision); } if (path) { if (!validatePath(path)) { throw new SvnError(`Invalid path: ${path}`); } args.push(normalizePath(path)); } let response; try { response = await executeSvnCommand(this.config, args); } catch (error: any) { // Detectar si SVN no está instalado if ((error.message.includes('spawn') && error.message.includes('ENOENT')) || error.code === 127) { const enhancedError = new SvnError( 'SVN no está instalado o no se encuentra en el PATH del sistema. Instala Subversion para usar este comando.' ); enhancedError.command = error.command; enhancedError.code = error.code; throw enhancedError; } // Detectar errores de red/conectividad y proporcionar mensajes más útiles if (error.message.includes('E175002') || error.message.includes('Unable to connect') || error.message.includes('Connection refused') || error.message.includes('Network is unreachable') || error.code === 1) { // Intentar con opciones que funcionen sin conectividad remota si es posible console.warn(`Log remoto falló, posible problema de conectividad: ${error.message}`); // Para comandos log, podemos intentar usar --offline si está disponible, // o proporcionar una respuesta vacía con información útil const enhancedError = new SvnError( `No se pudo obtener el historial de cambios. Posibles causas: - Sin conectividad al servidor SVN - Credenciales requeridas pero no proporcionadas - Servidor SVN temporalmente inaccesible - Working copy no sincronizado con el repositorio remoto` ); enhancedError.command = error.command; enhancedError.stderr = error.stderr; enhancedError.code = error.code; throw enhancedError; } // Re-lanzar otros errores sin modificar throw error; } const logEntries = parseLogOutput(cleanOutput(response.data as string)); return { success: true, data: logEntries, command: response.command, workingDirectory: response.workingDirectory, executionTime: response.executionTime }; } catch (error: any) { this.handleSvnError(error, 'get SVN log'); } }
- index.ts:204-242 (registration)MCP server.tool registration for 'svn_log'. Includes input schema validation with zod, calls SvnService.getLog handler, formats results as formatted markdown text response.server.tool( "svn_log", "Ver historial de commits del repositorio", { path: z.string().optional().describe("Ruta específica"), limit: z.number().optional().default(10).describe("Número máximo de entradas"), revision: z.string().optional().describe("Revisión específica o rango (ej: 100:200)") }, async (args) => { try { const result = await getSvnService().getLog(args.path, args.limit, args.revision); const logEntries = result.data!; if (logEntries.length === 0) { return { content: [{ type: "text", text: "📝 **No se encontraron entradas en el log**" }], }; } const logText = `📚 **Historial SVN** (${logEntries.length} entradas)\n\n` + logEntries.map((entry, index) => `**${index + 1}. Revisión ${entry.revision}**\n` + `👤 **Autor:** ${entry.author}\n` + `📅 **Fecha:** ${entry.date}\n` + `💬 **Mensaje:** ${entry.message || 'Sin mensaje'}\n` + `---` ).join('\n\n') + `\n**Tiempo de Ejecución:** ${formatDuration(result.executionTime || 0)}`; return { content: [{ type: "text", text: logText }], }; } catch (error: any) { return { content: [{ type: "text", text: `❌ **Error:** ${error.message}` }], }; } } );
- index.ts:207-211 (schema)Zod input schema for svn_log tool parameters: optional path, limit (default 10), revision range.{ path: z.string().optional().describe("Ruta específica"), limit: z.number().optional().default(10).describe("Número máximo de entradas"), revision: z.string().optional().describe("Revisión específica o rango (ej: 100:200)") },
- common/utils.ts:303-343 (helper)Helper function that parses raw 'svn log' command output into structured array of SvnLogEntry objects by splitting on SVN log separators and regex matching headers./** * Parsear output de svn log */ export function parseLogOutput(output: string): SvnLogEntry[] { const entries: SvnLogEntry[] = []; if (!output || output.trim().length === 0) { return entries; } // Dividir por las líneas separadoras de SVN log const logEntries = output.split(/^-{72}$/gm).filter(entry => entry.trim()); for (const entryText of logEntries) { const lines = entryText.trim().split('\n'); if (lines.length < 2) continue; const headerLine = lines[0]; // Patrón más flexible para el header const headerMatch = headerLine.match(/^r(\d+)\s*\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|\s*(.*)$/); if (headerMatch) { try { const [, revision, author, date, details] = headerMatch; const message = lines.slice(2).join('\n').trim(); entries.push({ revision: parseInt(revision, 10), author: author.trim(), date: date.trim(), message: message || 'Sin mensaje' }); } catch (parseError) { console.warn(`Warning: Failed to parse log entry: ${parseError}`); continue; } } } return entries; }
- common/types.ts:59-65 (schema)TypeScript interface defining the structure of a single SVN log entry used as output type for the parsed log.export interface SvnLogEntry { revision: number; author: string; date: string; message: string; changedPaths?: SvnChangedPath[]; }