@@ -62,6 +62,7 @@ async function readSnapshotFile(filePath: string): Promise<StoredSnapshot | null
6262 error,
6363 bytes : Buffer . byteLength ( raw , 'utf8' ) ,
6464 } ) ;
65+ await removeFile ( filePath ) ;
6566 return null ;
6667 }
6768}
@@ -76,6 +77,25 @@ async function removeFile(filePath: string): Promise<void> {
7677 }
7778}
7879
80+ async function atomicWriteFile ( filePath : string , contents : string ) : Promise < void > {
81+ const dir = path . dirname ( filePath ) ;
82+ const base = path . basename ( filePath ) ;
83+ const tmpPath = path . join ( dir , `.${ base } .${ process . pid } .${ Date . now ( ) } .tmp` ) ;
84+ await fs . promises . writeFile ( tmpPath , contents , 'utf8' ) ;
85+ try {
86+ await fs . promises . rename ( tmpPath , filePath ) ;
87+ } catch ( error ) {
88+ const code = ( error as NodeJS . ErrnoException ) ?. code ;
89+ if ( code === 'EEXIST' || code === 'EPERM' ) {
90+ await fs . promises . rm ( filePath , { force : true } ) ;
91+ await fs . promises . rename ( tmpPath , filePath ) ;
92+ return ;
93+ }
94+ await fs . promises . rm ( tmpPath , { force : true } ) ;
95+ throw error ;
96+ }
97+ }
98+
7999async function listSnapshots ( ) : Promise <
80100 Array < { id : string ; path : string ; stats : StoredSnapshot } >
81101> {
@@ -121,7 +141,7 @@ class TerminalSnapshotService {
121141 }
122142
123143 await ensureDir ( ) ;
124- await fs . promises . writeFile ( snapshotPath ( id ) , json , 'utf8' ) ;
144+ await atomicWriteFile ( snapshotPath ( id ) , json ) ;
125145 await this . pruneIfNeeded ( id ) ;
126146 return { ok : true } ;
127147 } catch ( error ) {
0 commit comments