Skip to content

Fix atomic writes and fs.constants flags in InitCommand and ConfigService#19

Merged
naheel0 merged 2 commits intoInitCommandfrom
copilot/sub-pr-18
Mar 23, 2026
Merged

Fix atomic writes and fs.constants flags in InitCommand and ConfigService#19
naheel0 merged 2 commits intoInitCommandfrom
copilot/sub-pr-18

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

Description

Three issues with config file writes: a TypeScript build failure from using non-existent fs.O_CREAT/O_EXCL/O_RDWR (should be fs.constants.*), a missing try/finally that could leak file descriptors, and non-atomic writeFileSync calls in both the backup/overwrite branches and ConfigService.saveConfig() that risk file corruption on interruption.

src/commands/InitCommand.ts

  • fs.O_CREAT | fs.O_EXCL | fs.O_RDWRfs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_RDWR (fixes CI build)
  • Wrapped writeFileSync/fsyncSync in try/finally to guarantee fd is always closed
  • Added atomicWriteFileSync helper: opens a .tmp-<pid>-<ts> file in the same directory with O_CREAT | O_EXCL | O_WRONLY, writes, fsyncs, closes, then renameSyncs into place; cleans up temp on rename failure
  • Both backup-then-replace and overwrite branches now use atomicWriteFileSync

src/services/ConfigService.ts

  • saveConfig() rewritten with the same temp-file + fsync + rename pattern, consistent temp naming (.tmp-<pid>-<ts> in config directory)
// Before — non-atomic, can corrupt on interruption
fs.writeFileSync(configPath, JSON.stringify(validated, null, 2), { mode: 0o600 });

// After — atomic
const tempPath = path.join(path.dirname(configPath), `.tmp-${process.pid}-${Date.now()}`);
const fd = fs.openSync(tempPath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600);
try {
  fs.writeFileSync(fd, JSON.stringify(validated, null, 2));
  fs.fsyncSync(fd);
} finally {
  fs.closeSync(fd);
}
fs.renameSync(tempPath, configPath);

Related Issue

Closes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📝 Documentation update
  • 🔧 Refactor / internal improvement
  • 🤖 CI/CD or tooling change
  • ⬆️ Dependency update

Checklist

  • I have read the CONTRIBUTING guidelines (if present)
  • My code follows the existing code style
  • I have added or updated tests that cover my changes
  • All existing tests pass locally
  • I have updated the documentation where necessary
  • My changes do not introduce new security vulnerabilities

How Has This Been Tested?

npm run build (previously failing, now passes) and npm test (lint + tsc --noEmit). CodeQL returned 0 alerts.

Screenshots (if applicable)

Additional Notes

The atomic write pattern mirrors the existing ConflictResolver.applyResolution() already in the codebase. Temp files are created in the same directory as the target to ensure rename is a same-filesystem operation.


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

… in InitCommand and ConfigService

Co-authored-by: jaseel0 <225665919+jaseel0@users.noreply.github.com>
Agent-Logs-Url: https://github.com/BeyteFlow/git-ai/sessions/53acba39-daa6-4e19-91d9-07b21288984a
Copilot AI changed the title [WIP] Refactor config file handling in InitCommand Fix atomic writes and fs.constants flags in InitCommand and ConfigService Mar 23, 2026
@naheel0 naheel0 marked this pull request as ready for review March 23, 2026 07:03
@naheel0 naheel0 merged commit 1b0832f into InitCommand Mar 23, 2026
2 checks passed
@naheel0 naheel0 deleted the copilot/sub-pr-18 branch March 23, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants