fix(format): Improve concurrency control in cache and rollback modules, refine gitignore custom section handling, and enhance Prettier file processing

This commit is contained in:
2025-08-08 06:50:58 +00:00
parent 74a8229e43
commit 74ecdde1ac
12 changed files with 265 additions and 68 deletions

View File

@@ -29,8 +29,9 @@ export class PrettierFormatter extends BaseFormatter {
'README.md',
'changelog.md',
'CHANGELOG.md',
'license',
'LICENSE',
// Skip files without extensions as prettier can't infer parser
// 'license',
// 'LICENSE',
'*.md',
];
@@ -102,40 +103,26 @@ export class PrettierFormatter extends BaseFormatter {
try {
await this.preExecute();
// Batch process files
const batchSize = 10; // Process 10 files at a time
const batches: IPlannedChange[][] = [];
logVerbose(`Processing ${changes.length} files sequentially`);
for (let i = 0; i < changes.length; i += batchSize) {
batches.push(changes.slice(i, i + batchSize));
}
logVerbose(
`Processing ${changes.length} files in ${batches.length} batches`,
);
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
// Process files sequentially to avoid prettier cache/state issues
for (let i = 0; i < changes.length; i++) {
const change = changes[i];
logVerbose(
`Processing batch ${i + 1}/${batches.length} (${batch.length} files)`,
`Processing file ${i + 1}/${changes.length}: ${change.path}`,
);
// Process batch in parallel
const promises = batch.map(async (change) => {
try {
await this.applyChange(change);
this.stats.recordFileOperation(this.name, change.type, true);
} catch (error) {
this.stats.recordFileOperation(this.name, change.type, false);
logger.log(
'error',
`Failed to format ${change.path}: ${error.message}`,
);
// Don't throw - continue with other files
}
});
await Promise.all(promises);
try {
await this.applyChange(change);
this.stats.recordFileOperation(this.name, change.type, true);
} catch (error) {
this.stats.recordFileOperation(this.name, change.type, false);
logger.log(
'error',
`Failed to format ${change.path}: ${error.message}`,
);
// Don't throw - continue with other files
}
}
await this.postExecute();
@@ -151,25 +138,71 @@ export class PrettierFormatter extends BaseFormatter {
if (change.type !== 'modify') return;
try {
// Validate the path before processing
if (!change.path || change.path.trim() === '') {
logger.log(
'error',
`Invalid empty path in change: ${JSON.stringify(change)}`,
);
throw new Error('Invalid empty path');
}
// Read current content
const content = plugins.smartfile.fs.toStringSync(change.path);
// Format with prettier
const prettier = await import('prettier');
const formatted = await prettier.format(content, {
filepath: change.path,
...(await this.getPrettierConfig()),
});
// Only write if content actually changed
if (formatted !== content) {
await this.modifyFile(change.path, formatted);
logVerbose(`Formatted ${change.path}`);
} else {
logVerbose(`No formatting changes for ${change.path}`);
// Skip files that prettier can't parse without explicit parser
const fileExt = plugins.path.extname(change.path).toLowerCase();
if (!fileExt || fileExt === '') {
// Files without extensions need explicit parser
logVerbose(
`Skipping ${change.path} - no file extension for parser inference`,
);
return;
}
try {
const formatted = await prettier.format(content, {
filepath: change.path,
...(await this.getPrettierConfig()),
});
// Only write if content actually changed
if (formatted !== content) {
// Debug: log the path being written
logVerbose(`Writing formatted content to: ${change.path}`);
await this.modifyFile(change.path, formatted);
logVerbose(`Formatted ${change.path}`);
} else {
logVerbose(`No formatting changes for ${change.path}`);
}
} catch (prettierError) {
// Check if it's a parser error
if (
prettierError.message &&
prettierError.message.includes('No parser could be inferred')
) {
logVerbose(`Skipping ${change.path} - ${prettierError.message}`);
return; // Skip this file silently
}
throw prettierError;
}
} catch (error) {
logger.log('error', `Failed to format ${change.path}: ${error.message}`);
// Log the full error stack for debugging mkdir issues
if (error.message && error.message.includes('mkdir')) {
logger.log(
'error',
`Failed to format ${change.path}: ${error.message}`,
);
logger.log('error', `Error stack: ${error.stack}`);
} else {
logger.log(
'error',
`Failed to format ${change.path}: ${error.message}`,
);
}
throw error;
}
}