@@ -257,12 +257,12 @@ private void IncrementalHistoryWrite()
257257 i -= 1 ;
258258 }
259259
260- WriteHistoryRange ( i + 1 , _history . Count - 1 , File . AppendText ) ;
260+ WriteHistoryRange ( i + 1 , _history . Count - 1 , overwritten : false ) ;
261261 }
262262
263263 private void SaveHistoryAtExit ( )
264264 {
265- WriteHistoryRange ( 0 , _history . Count - 1 , File . CreateText ) ;
265+ WriteHistoryRange ( 0 , _history . Count - 1 , overwritten : true ) ;
266266 }
267267
268268 private int historyErrorReportedCount ;
@@ -321,70 +321,99 @@ private bool WithHistoryFileMutexDo(int timeout, Action action)
321321 return true ;
322322 }
323323
324- private void WriteHistoryRange ( int start , int end , Func < string , StreamWriter > fileOpener )
324+ private void WriteHistoryRange ( int start , int end , bool overwritten )
325325 {
326326 WithHistoryFileMutexDo ( 100 , ( ) =>
327327 {
328- if ( ! MaybeReadHistoryFile ( ) )
329- return ;
330-
331328 bool retry = true ;
332- retry_after_creating_directory :
329+ // Get the new content since the last sync.
330+ List < string > historyLines = overwritten ? null : ReadHistoryFileIncrementally ( ) ;
331+
333332 try
334333 {
335- using ( var file = fileOpener ( Options . HistorySavePath ) )
334+ retry_after_creating_directory :
335+ try
336336 {
337- for ( var i = start ; i <= end ; i ++ )
337+ using ( var file = overwritten ? File . CreateText ( Options . HistorySavePath ) : File . AppendText ( Options . HistorySavePath ) )
338338 {
339- HistoryItem item = _history [ i ] ;
340- item . _saved = true ;
339+ for ( var i = start ; i <= end ; i ++ )
340+ {
341+ HistoryItem item = _history [ i ] ;
342+ item . _saved = true ;
341343
342- // Actually, skip writing sensitive items to file.
343- if ( item . _sensitive ) { continue ; }
344+ // Actually, skip writing sensitive items to file.
345+ if ( item . _sensitive ) { continue ; }
344346
345- var line = item . CommandLine . Replace ( "\n " , "`\n " ) ;
346- file . WriteLine ( line ) ;
347+ var line = item . CommandLine . Replace ( "\n " , "`\n " ) ;
348+ file . WriteLine ( line ) ;
349+ }
350+ }
351+ var fileInfo = new FileInfo ( Options . HistorySavePath ) ;
352+ _historyFileLastSavedSize = fileInfo . Length ;
353+ }
354+ catch ( DirectoryNotFoundException )
355+ {
356+ // Try making the directory, but just once
357+ if ( retry )
358+ {
359+ retry = false ;
360+ Directory . CreateDirectory ( Path . GetDirectoryName ( Options . HistorySavePath ) ) ;
361+ goto retry_after_creating_directory ;
347362 }
348363 }
349- var fileInfo = new FileInfo ( Options . HistorySavePath ) ;
350- _historyFileLastSavedSize = fileInfo . Length ;
351364 }
352- catch ( DirectoryNotFoundException )
365+ finally
353366 {
354- // Try making the directory, but just once
355- if ( retry )
367+ if ( historyLines != null )
356368 {
357- retry = false ;
358- Directory . CreateDirectory ( Path . GetDirectoryName ( Options . HistorySavePath ) ) ;
359- goto retry_after_creating_directory ;
369+ // Populate new history from other sessions to the history queue after we are done
370+ // with writing the specified range to the file.
371+ // We do it at this point to make sure the range of history items from 'start' to
372+ // 'end' do not get changed before the writing to the file.
373+ UpdateHistoryFromFile ( historyLines , fromDifferentSession : true , fromInitialRead : false ) ;
360374 }
361375 }
362376 } ) ;
363377 }
364378
379+ /// <summary>
380+ /// Helper method to read the incremental part of the history file.
381+ /// Note: the call to this method should be guarded by the mutex that protects the history file.
382+ /// </summary>
383+ private List < string > ReadHistoryFileIncrementally ( )
384+ {
385+ var fileInfo = new FileInfo ( Options . HistorySavePath ) ;
386+ if ( fileInfo . Exists && fileInfo . Length != _historyFileLastSavedSize )
387+ {
388+ var historyLines = new List < string > ( ) ;
389+ using ( var fs = new FileStream ( Options . HistorySavePath , FileMode . Open ) )
390+ using ( var sr = new StreamReader ( fs ) )
391+ {
392+ fs . Seek ( _historyFileLastSavedSize , SeekOrigin . Begin ) ;
393+
394+ while ( ! sr . EndOfStream )
395+ {
396+ historyLines . Add ( sr . ReadLine ( ) ) ;
397+ }
398+ }
399+
400+ _historyFileLastSavedSize = fileInfo . Length ;
401+ return historyLines . Count > 0 ? historyLines : null ;
402+ }
403+
404+ return null ;
405+ }
406+
365407 private bool MaybeReadHistoryFile ( )
366408 {
367409 if ( Options . HistorySaveStyle == HistorySaveStyle . SaveIncrementally )
368410 {
369411 return WithHistoryFileMutexDo ( 1000 , ( ) =>
370412 {
371- var fileInfo = new FileInfo ( Options . HistorySavePath ) ;
372- if ( fileInfo . Exists && fileInfo . Length != _historyFileLastSavedSize )
413+ List < string > historyLines = ReadHistoryFileIncrementally ( ) ;
414+ if ( historyLines != null )
373415 {
374- var historyLines = new List < string > ( ) ;
375- using ( var fs = new FileStream ( Options . HistorySavePath , FileMode . Open ) )
376- using ( var sr = new StreamReader ( fs ) )
377- {
378- fs . Seek ( _historyFileLastSavedSize , SeekOrigin . Begin ) ;
379-
380- while ( ! sr . EndOfStream )
381- {
382- historyLines . Add ( sr . ReadLine ( ) ) ;
383- }
384- }
385416 UpdateHistoryFromFile ( historyLines , fromDifferentSession : true , fromInitialRead : false ) ;
386-
387- _historyFileLastSavedSize = fileInfo . Length ;
388417 }
389418 } ) ;
390419 }
0 commit comments