mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 20:17:45 +00:00
fix(backup): create backups only when settings content changes
Previously, PUT /api/settings/:profile created a backup on every request regardless of whether the content actually changed. This led to hundreds of identical backup files accumulating in ~/.ccs/backups/. Changes: - Compare existing content with new content before creating backup - Reuse computed newContent for atomic write (DRY) - Make hook injection idempotent by checking content before write Fixes #433
This commit is contained in:
@@ -123,11 +123,17 @@ export function ensureProfileHooks(profileName: string): boolean {
|
||||
// Clean up any duplicates that may have accumulated (Windows path bug fix)
|
||||
const hadDuplicates = deduplicateCcsHooks(settings);
|
||||
if (hadDuplicates) {
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
||||
if (process.env.CCS_DEBUG) {
|
||||
console.error(
|
||||
info(`Removed duplicate WebSearch hooks from ${profileName}.settings.json`)
|
||||
);
|
||||
// Re-read file to compare with modified settings (deduplicateCcsHooks mutates in-place)
|
||||
const newContent = JSON.stringify(settings, null, 2);
|
||||
const existingContent = fs.readFileSync(settingsPath, 'utf8');
|
||||
// Only write if content actually changed
|
||||
if (newContent !== existingContent) {
|
||||
fs.writeFileSync(settingsPath, newContent, 'utf8');
|
||||
if (process.env.CCS_DEBUG) {
|
||||
console.error(
|
||||
info(`Removed duplicate WebSearch hooks from ${profileName}.settings.json`)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update timeout if needed
|
||||
|
||||
@@ -156,16 +156,21 @@ router.put('/:profile', (req: Request, res: Response): void => {
|
||||
}
|
||||
}
|
||||
|
||||
// Create backup only if file exists
|
||||
// Create backup only if file exists AND content actually changed
|
||||
let backupPath: string | undefined;
|
||||
const newContent = JSON.stringify(settings, null, 2) + '\n';
|
||||
if (fileExists) {
|
||||
const backupDir = path.join(ccsDir, 'backups');
|
||||
if (!fs.existsSync(backupDir)) {
|
||||
fs.mkdirSync(backupDir, { recursive: true });
|
||||
const existingContent = fs.readFileSync(settingsPath, 'utf8');
|
||||
// Only create backup if content differs
|
||||
if (existingContent !== newContent) {
|
||||
const backupDir = path.join(ccsDir, 'backups');
|
||||
if (!fs.existsSync(backupDir)) {
|
||||
fs.mkdirSync(backupDir, { recursive: true });
|
||||
}
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
backupPath = path.join(backupDir, `${profile}.${timestamp}.settings.json`);
|
||||
fs.copyFileSync(settingsPath, backupPath);
|
||||
}
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
backupPath = path.join(backupDir, `${profile}.${timestamp}.settings.json`);
|
||||
fs.copyFileSync(settingsPath, backupPath);
|
||||
}
|
||||
|
||||
// Ensure directory exists for new files
|
||||
@@ -175,7 +180,7 @@ router.put('/:profile', (req: Request, res: Response): void => {
|
||||
|
||||
// Write new settings atomically
|
||||
const tempPath = settingsPath + '.tmp';
|
||||
fs.writeFileSync(tempPath, JSON.stringify(settings, null, 2) + '\n');
|
||||
fs.writeFileSync(tempPath, newContent);
|
||||
fs.renameSync(tempPath, settingsPath);
|
||||
|
||||
const newStat = fs.statSync(settingsPath);
|
||||
|
||||
Reference in New Issue
Block a user