@@ -198,26 +198,93 @@ impl History for FileBackedHistory {
198
198
"Invalid ID (not usize)" ,
199
199
) )
200
200
} ) ?;
201
- if self . len_on_disk <= id {
202
- self . entries . remove ( id) ;
203
- Ok ( ( ) )
204
- } else {
205
- // Since no ID is written to disk, it's not possible to delete them.
206
- // E.g. consider another instance having deleted entries, after this instance
207
- // loaded the file.
208
- Err ( ReedlineError (
209
- ReedlineErrorVariants :: HistoryFeatureUnsupported {
210
- history : "FileBackedHistory" ,
211
- feature : "removing entries" ,
212
- } ,
213
- ) )
201
+
202
+ let delete = self . entries [ id] . clone ( ) ;
203
+ let mut i = 0 ;
204
+ while i < self . entries . len ( ) {
205
+ if self . entries [ i] == delete {
206
+ self . entries . remove ( i) ;
207
+ if i < self . len_on_disk {
208
+ self . len_on_disk -= 1 ;
209
+ }
210
+ } else {
211
+ i += 1 ;
212
+ }
214
213
}
214
+
215
+ self . sync_and_delete_item ( Some ( & delete) )
216
+ . map_err ( |e| ReedlineError ( ReedlineErrorVariants :: IOError ( e) ) )
215
217
}
216
218
217
219
/// Writes unwritten history contents to disk.
218
220
///
219
221
/// If file would exceed `capacity` truncates the oldest entries.
220
222
fn sync ( & mut self ) -> std:: io:: Result < ( ) > {
223
+ self . sync_and_delete_item ( None )
224
+ }
225
+
226
+ fn session ( & self ) -> Option < HistorySessionId > {
227
+ self . session
228
+ }
229
+ }
230
+
231
+ impl FileBackedHistory {
232
+ /// Creates a new in-memory history that remembers `n <= capacity` elements
233
+ ///
234
+ /// # Panics
235
+ ///
236
+ /// If `capacity == usize::MAX`
237
+ pub fn new ( capacity : usize ) -> Self {
238
+ if capacity == usize:: MAX {
239
+ panic ! ( "History capacity too large to be addressed safely" ) ;
240
+ }
241
+ FileBackedHistory {
242
+ capacity,
243
+ entries : VecDeque :: new ( ) ,
244
+ file : None ,
245
+ len_on_disk : 0 ,
246
+ session : None ,
247
+ }
248
+ }
249
+
250
+ /// Creates a new history with an associated history file.
251
+ ///
252
+ /// History file format: commands separated by new lines.
253
+ /// If file exists file will be read otherwise empty file will be created.
254
+ ///
255
+ ///
256
+ /// **Side effects:** creates all nested directories to the file
257
+ ///
258
+ pub fn with_file ( capacity : usize , file : PathBuf ) -> std:: io:: Result < Self > {
259
+ let mut hist = Self :: new ( capacity) ;
260
+ if let Some ( base_dir) = file. parent ( ) {
261
+ std:: fs:: create_dir_all ( base_dir) ?;
262
+ }
263
+ hist. file = Some ( file) ;
264
+ hist. sync ( ) ?;
265
+ Ok ( hist)
266
+ }
267
+
268
+ // this history doesn't store any info except command line
269
+ fn construct_entry ( id : Option < HistoryItemId > , command_line : String ) -> HistoryItem {
270
+ HistoryItem {
271
+ id,
272
+ start_timestamp : None ,
273
+ command_line,
274
+ session_id : None ,
275
+ hostname : None ,
276
+ cwd : None ,
277
+ duration : None ,
278
+ exit_status : None ,
279
+ more_info : None ,
280
+ }
281
+ }
282
+
283
+ /// Writes unwritten history contents to disk, and optionally deletes
284
+ /// all occurences of the provided item.
285
+ ///
286
+ /// If file would exceed `capacity` truncates the oldest entries.
287
+ fn sync_and_delete_item ( & mut self , delete : Option < & str > ) -> std:: io:: Result < ( ) > {
221
288
if let Some ( fname) = & self . file {
222
289
// The unwritten entries
223
290
let own_entries = self . entries . range ( self . len_on_disk ..) ;
@@ -236,17 +303,26 @@ impl History for FileBackedHistory {
236
303
let mut writer_guard = f_lock. write ( ) ?;
237
304
let ( mut foreign_entries, truncate) = {
238
305
let reader = BufReader :: new ( writer_guard. deref ( ) ) ;
306
+ let mut deletions = false ;
239
307
let mut from_file = reader
240
308
. lines ( )
241
309
. map ( |o| o. map ( |i| decode_entry ( & i) ) )
310
+ . filter ( |x| {
311
+ if x. as_deref ( ) . ok ( ) == delete {
312
+ deletions = true ;
313
+ false
314
+ } else {
315
+ true
316
+ }
317
+ } )
242
318
. collect :: < std:: io:: Result < VecDeque < _ > > > ( ) ?;
243
319
if from_file. len ( ) + own_entries. len ( ) > self . capacity {
244
320
(
245
321
from_file. split_off ( from_file. len ( ) - ( self . capacity - own_entries. len ( ) ) ) ,
246
322
true ,
247
323
)
248
324
} else {
249
- ( from_file, false )
325
+ ( from_file, deletions )
250
326
}
251
327
} ;
252
328
@@ -282,63 +358,6 @@ impl History for FileBackedHistory {
282
358
}
283
359
Ok ( ( ) )
284
360
}
285
-
286
- fn session ( & self ) -> Option < HistorySessionId > {
287
- self . session
288
- }
289
- }
290
-
291
- impl FileBackedHistory {
292
- /// Creates a new in-memory history that remembers `n <= capacity` elements
293
- ///
294
- /// # Panics
295
- ///
296
- /// If `capacity == usize::MAX`
297
- pub fn new ( capacity : usize ) -> Self {
298
- if capacity == usize:: MAX {
299
- panic ! ( "History capacity too large to be addressed safely" ) ;
300
- }
301
- FileBackedHistory {
302
- capacity,
303
- entries : VecDeque :: new ( ) ,
304
- file : None ,
305
- len_on_disk : 0 ,
306
- session : None ,
307
- }
308
- }
309
-
310
- /// Creates a new history with an associated history file.
311
- ///
312
- /// History file format: commands separated by new lines.
313
- /// If file exists file will be read otherwise empty file will be created.
314
- ///
315
- ///
316
- /// **Side effects:** creates all nested directories to the file
317
- ///
318
- pub fn with_file ( capacity : usize , file : PathBuf ) -> std:: io:: Result < Self > {
319
- let mut hist = Self :: new ( capacity) ;
320
- if let Some ( base_dir) = file. parent ( ) {
321
- std:: fs:: create_dir_all ( base_dir) ?;
322
- }
323
- hist. file = Some ( file) ;
324
- hist. sync ( ) ?;
325
- Ok ( hist)
326
- }
327
-
328
- // this history doesn't store any info except command line
329
- fn construct_entry ( id : Option < HistoryItemId > , command_line : String ) -> HistoryItem {
330
- HistoryItem {
331
- id,
332
- start_timestamp : None ,
333
- command_line,
334
- session_id : None ,
335
- hostname : None ,
336
- cwd : None ,
337
- duration : None ,
338
- exit_status : None ,
339
- more_info : None ,
340
- }
341
- }
342
361
}
343
362
344
363
impl Drop for FileBackedHistory {
0 commit comments