mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-26 18:35:05 +00:00
fix: normalize apostrophes inside quoted Windows paths
(cherry picked from commit 8ab9358e18)
This commit is contained in:
2 files changed
+32
-2
No files matched your search
@@ -21,8 +21,9 @@ function normalizeFailureReason(reason) {
|
||||
.replace(/\d{4}-\d{2}-\d{2}[t ]\d{2}:\d{2}:\d{2}[.\dz]*/g, '<timestamp>')
|
||||
// Strip UUIDs (already lowercased)
|
||||
.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g, '<uuid>')
|
||||
// Quoted Windows paths preserve spaces in the final path component.
|
||||
.replace(/(["'])(?:[a-z]:[\\/]|\\\\)[^\r\n]*?\1/gu, '$1<path>$1')
|
||||
// Quoted Windows paths preserve spaces and apostrophes inside path components.
|
||||
// A closing quote must be followed by a delimiter, not another name character.
|
||||
.replace(/(["'])(?:[a-z]:[\\/]|\\\\)[^\r\n]*?\1(?=[:\s),;.!?]|$)/gu, '$1<path>$1')
|
||||
// Directories may contain spaces, but trailing whitespace separates diagnostic prose.
|
||||
// Spaced leaves need an extension before a colon, or quotes; preserve extensionless diagnostics.
|
||||
.replace(/(?:\b[a-z]:|\\)[\\/](?:[^\\/:*?"<>|\r\n]*[^\s\\/:*?"<>|][\\/])*[^\s\\/:*?"<>|(),;]+(?: [^\\/:*?"<>|\r\n]*\.[^\s\\/:*?"<>|]+(?=:))?[\\/]*/gu, '<path>')
|
||||
|
||||
@@ -96,6 +96,21 @@ async function runTests() {
|
||||
}
|
||||
})) passed += 1; else failed += 1;
|
||||
|
||||
if (await test('normalizeFailureReason keeps apostrophes inside quoted Windows paths', async () => {
|
||||
for (const filePath of [
|
||||
String.raw`C:\Users\O'Brien\report.js`,
|
||||
String.raw`D:\Users\D'Arcy\my report.js`,
|
||||
String.raw`\\server\shared files\L'Heureux\report.js`,
|
||||
]) {
|
||||
assert.strictEqual(normalizeFailureReason(`Cannot open '${filePath}': permission denied`),
|
||||
"cannot open '<path>': permission denied");
|
||||
}
|
||||
assert.notStrictEqual(
|
||||
normalizeFailureReason(String.raw`Cannot open 'C:\Users\O'Brien\report.js': permission denied`),
|
||||
normalizeFailureReason(String.raw`Cannot open 'C:\Users\O'Brien\report.js': file missing`)
|
||||
);
|
||||
})) passed += 1; else failed += 1;
|
||||
|
||||
if (await test('normalizeFailureReason preserves diagnostics after unquoted Windows paths', async () => {
|
||||
for (const filePath of [
|
||||
String.raw`C:\Program Files\node`,
|
||||
@@ -267,6 +282,20 @@ async function runTests() {
|
||||
assert.strictEqual(generateReport(backupPatterns).status, 'attention_needed');
|
||||
})) passed += 1; else failed += 1;
|
||||
|
||||
if (await test('inspect groups quoted Windows paths with apostrophes and preserves diagnostics', async () => {
|
||||
const runs = [
|
||||
String.raw`Cannot open 'C:\Users\O'Brien\report.js': permission denied`,
|
||||
String.raw`Cannot open 'D:\Users\D'Arcy\my report.js': permission denied`,
|
||||
String.raw`Cannot open '\\server\shared files\L'Heureux\report.js': permission denied`,
|
||||
].map((failureReason, index) => makeSkillRun({ id: `apostrophe-${index}`, failureReason }));
|
||||
const report = inspect({ getStatus: () => ({ skillRuns: { recent: runs } }) });
|
||||
assert.strictEqual(report.status, 'attention_needed');
|
||||
assert.strictEqual(report.patternCount, 1);
|
||||
assert.strictEqual(report.patterns[0].count, 3);
|
||||
assert.strictEqual(report.patterns[0].normalizedReason, "cannot open '<path>': permission denied");
|
||||
assert.deepStrictEqual(report.patterns[0].rawReasons, runs.map(run => run.failureReason));
|
||||
})) passed += 1; else failed += 1;
|
||||
|
||||
if (await test('detectPatterns tracks unique session IDs and versions', async () => {
|
||||
const runs = [
|
||||
makeSkillRun({ id: 'r1', sessionId: 'sess-1', skillVersion: '1.0.0', failureReason: 'err' }),
|
||||
|
||||
Reference in new issue
Block a user