From b498a25965e8536657ecac3f7f177aacdda5dfce Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Thu, 12 Feb 2026 23:44:06 +0300 Subject: [PATCH] refactor(git): use spawnAsync for command execution and improve commit log retrieval --- server/routes/git.js | 51 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/server/routes/git.js b/server/routes/git.js index 5f6d803..e6fecee 100755 --- a/server/routes/git.js +++ b/server/routes/git.js @@ -1,5 +1,5 @@ import express from 'express'; -import { exec } from 'child_process'; +import { exec, spawn } from 'child_process'; import { promisify } from 'util'; import path from 'path'; import { promises as fs } from 'fs'; @@ -10,6 +10,43 @@ import { spawnCursor } from '../cursor-cli.js'; const router = express.Router(); const execAsync = promisify(exec); +function spawnAsync(command, args, options = {}) { + return new Promise((resolve, reject) => { + const child = spawn(command, args, { + ...options, + shell: false, + }); + + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => { + stdout += data.toString(); + }); + + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + child.on('error', (error) => { + reject(error); + }); + + child.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + return; + } + + const error = new Error(`Command failed: ${command} ${args.join(' ')}`); + error.code = code; + error.stdout = stdout; + error.stderr = stderr; + reject(error); + }); + }); +} + // Helper function to get the actual project path from the encoded project name async function getActualProjectPath(projectName) { try { @@ -442,11 +479,17 @@ router.get('/commits', async (req, res) => { try { const projectPath = await getActualProjectPath(project); + await validateGitRepository(projectPath); + const parsedLimit = Number.parseInt(String(limit), 10); + const safeLimit = Number.isFinite(parsedLimit) && parsedLimit > 0 + ? Math.min(parsedLimit, 100) + : 10; // Get commit log with stats - const { stdout } = await execAsync( - `git log --pretty=format:'%H|%an|%ae|%ad|%s' --date=relative -n ${limit}`, - { cwd: projectPath } + const { stdout } = await spawnAsync( + 'git', + ['log', '--pretty=format:%H|%an|%ae|%ad|%s', '--date=relative', '-n', String(safeLimit)], + { cwd: projectPath }, ); const commits = stdout