Files
automaker/apps/server/src/routes/worktree/routes/status.ts
webdevcody 43481c2bab refactor: sanitize featureId for worktree paths across multiple handlers
- Updated createDiffsHandler, createFileDiffHandler, createInfoHandler, createStatusHandler, and auto-mode service to sanitize featureId when constructing worktree paths.
- Ensured consistent handling of featureId to prevent issues with invalid characters in branch names.
- Added branchName support in UI components to enhance feature visibility and management.

This change improves the robustness of worktree operations and enhances user experience by ensuring valid paths are used throughout the application.
2026-01-19 17:35:01 -05:00

74 lines
2.2 KiB
TypeScript

/**
* POST /status endpoint - Get worktree status
*/
import type { Request, Response } from 'express';
import { exec } from 'child_process';
import { promisify } from 'util';
import path from 'path';
import * as secureFs from '../../../lib/secure-fs.js';
import { getErrorMessage, logError } from '../common.js';
const execAsync = promisify(exec);
export function createStatusHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureId } = req.body as {
projectPath: string;
featureId: string;
};
if (!projectPath || !featureId) {
res.status(400).json({
success: false,
error: 'projectPath and featureId required',
});
return;
}
// Git worktrees are stored in project directory
// Sanitize featureId the same way it's sanitized when creating worktrees
// (see create.ts: branchName.replace(/[^a-zA-Z0-9_-]/g, '-'))
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
try {
await secureFs.access(worktreePath);
const { stdout: status } = await execAsync('git status --porcelain', {
cwd: worktreePath,
});
const files = status
.split('\n')
.filter(Boolean)
.map((line) => line.slice(3));
const { stdout: diffStat } = await execAsync('git diff --stat', {
cwd: worktreePath,
});
const { stdout: logOutput } = await execAsync('git log --oneline -5 --format="%h %s"', {
cwd: worktreePath,
});
res.json({
success: true,
modifiedFiles: files.length,
files,
diffStat: diffStat.trim(),
recentCommits: logOutput.trim().split('\n').filter(Boolean),
});
} catch {
res.json({
success: true,
modifiedFiles: 0,
files: [],
diffStat: '',
recentCommits: [],
});
}
} catch (error) {
logError(error, 'Get worktree status failed');
res.status(500).json({ success: false, error: getErrorMessage(error) });
}
};
}