mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-28 04:25:11 +02:00
fix(install): pin Claude settings parent during atomic replacement
Reject directory replacement after temporary file creation or staging, preserve unrelated files during cleanup, and retry settings edits observed before the final rename. Add three regression tests for the review findings.
This commit is contained in:
@@ -13,21 +13,34 @@ function writeFileAtomic(filePath, content, options = {}) {
|
||||
);
|
||||
const mode = options.mode || 0o600;
|
||||
|
||||
if (options.validateParent) options.validateParent();
|
||||
fs.mkdirSync(parentDir, { recursive: true });
|
||||
|
||||
let descriptor;
|
||||
try {
|
||||
if (options.validateParent) options.validateParent();
|
||||
descriptor = fs.openSync(tempPath, 'wx', mode);
|
||||
if (options.validateParent) options.validateParent();
|
||||
fs.writeFileSync(descriptor, content, { encoding: options.encoding || 'utf8' });
|
||||
fs.fsyncSync(descriptor);
|
||||
fs.closeSync(descriptor);
|
||||
descriptor = undefined;
|
||||
if (options.validateParent) options.validateParent();
|
||||
if (options.beforeRename) options.beforeRename();
|
||||
fs.renameSync(tempPath, resolvedPath);
|
||||
} catch (error) {
|
||||
if (descriptor !== undefined) {
|
||||
fs.closeSync(descriptor);
|
||||
}
|
||||
fs.rmSync(tempPath, { force: true });
|
||||
// If the parent was replaced, this pathname may now name somebody else's
|
||||
// file. Leave the private staging file in its original directory.
|
||||
let parentUnchanged = true;
|
||||
try {
|
||||
if (options.validateParent) options.validateParent();
|
||||
} catch (_error) {
|
||||
parentUnchanged = false;
|
||||
}
|
||||
if (parentUnchanged) fs.rmSync(tempPath, { force: true });
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user