Skip to content

Commit bc95747

Browse files
committed
Local delete: extract sink-based inner functions
- Rename outer `delete_files_with_progress` body into `delete_files_with_progress_inner(events: &dyn OperationEventSink, ...)` and add a thin outer wrapper that constructs `TauriEventSink`. Same pattern for the async volume path: `delete_volume_files_with_progress` becomes an outer wrapper around `delete_volume_files_with_progress_inner`. - `scan_volume_recursive` (helper) switches from `&AppHandle` to `&dyn OperationEventSink`. - All `app.emit(...)` and `state.emit_progress_via_app(...)` sites route through the sink (`emit_complete`, `emit_cancelled`, `emit_source_item_done`, `emit_dry_run_complete`, `emit_progress_via_sink`). - No behavior change. Closes the M1.5 helper migration: every local write operation has a sink-based testable inner alongside the public `&AppHandle` outer wrapper.
1 parent 9d7c69e commit bc95747

1 file changed

Lines changed: 83 additions & 86 deletions

File tree

  • apps/desktop/src-tauri/src/file_system/write_operations

apps/desktop/src-tauri/src/file_system/write_operations/delete.rs

Lines changed: 83 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use super::helpers::spawn_async_sync;
99
use super::scan::{SourceItemTracker, scan_sources};
1010
use super::state::{WriteOperationState, update_operation_status};
1111
use super::types::{
12-
DryRunResult, IoResultExt, TauriEventSink, WriteCancelledEvent, WriteCompleteEvent, WriteOperationConfig,
13-
WriteOperationError, WriteOperationPhase, WriteOperationType, WriteProgressEvent, WriteSourceItemDoneEvent,
12+
DryRunResult, IoResultExt, OperationEventSink, TauriEventSink, WriteCancelledEvent, WriteCompleteEvent,
13+
WriteOperationConfig, WriteOperationError, WriteOperationPhase, WriteOperationType, WriteProgressEvent,
14+
WriteSourceItemDoneEvent,
1415
};
1516
use super::volume_copy::map_volume_error;
1617
use crate::file_system::volume::Volume;
@@ -26,15 +27,22 @@ pub(super) fn delete_files_with_progress(
2627
sources: &[PathBuf],
2728
config: &WriteOperationConfig,
2829
) -> Result<(), WriteOperationError> {
29-
use tauri::Emitter;
30-
3130
let events = TauriEventSink::new(app.clone());
31+
delete_files_with_progress_inner(&events, operation_id, state, sources, config)
32+
}
3233

34+
pub(super) fn delete_files_with_progress_inner(
35+
events: &dyn OperationEventSink,
36+
operation_id: &str,
37+
state: &Arc<WriteOperationState>,
38+
sources: &[PathBuf],
39+
config: &WriteOperationConfig,
40+
) -> Result<(), WriteOperationError> {
3341
// Phase 1: Scan to get file count (delete uses default sorting)
3442
let scan_result = scan_sources(
3543
sources,
3644
state,
37-
&events,
45+
events,
3846
operation_id,
3947
WriteOperationType::Delete,
4048
config.sort_column,
@@ -43,17 +51,15 @@ pub(super) fn delete_files_with_progress(
4351

4452
// Handle dry-run mode (delete has no conflicts)
4553
if config.dry_run {
46-
let result = DryRunResult {
54+
events.emit_dry_run_complete(DryRunResult {
4755
operation_id: operation_id.to_string(),
4856
operation_type: WriteOperationType::Delete,
4957
files_total: scan_result.file_count,
5058
bytes_total: scan_result.total_bytes,
5159
conflicts_total: 0,
5260
conflicts: Vec::new(),
5361
conflicts_sampled: false,
54-
};
55-
56-
let _ = app.emit("dry-run-complete", result);
62+
});
5763
return Ok(());
5864
}
5965

@@ -68,15 +74,12 @@ pub(super) fn delete_files_with_progress(
6874
for file_info in &scan_result.files {
6975
// Check cancellation
7076
if super::state::is_cancelled(&state.intent) {
71-
let _ = app.emit(
72-
"write-cancelled",
73-
WriteCancelledEvent {
74-
operation_id: operation_id.to_string(),
75-
operation_type: WriteOperationType::Delete,
76-
files_processed: files_done,
77-
rolled_back: false, // Delete operations can't be rolled back
78-
},
79-
);
77+
events.emit_cancelled(WriteCancelledEvent {
78+
operation_id: operation_id.to_string(),
79+
operation_type: WriteOperationType::Delete,
80+
files_processed: files_done,
81+
rolled_back: false, // Delete operations can't be rolled back
82+
});
8083
return Err(WriteOperationError::Cancelled {
8184
message: "Operation cancelled by user".to_string(),
8285
});
@@ -91,20 +94,17 @@ pub(super) fn delete_files_with_progress(
9194
bytes_done += file_size;
9295

9396
if let Some(source_path) = tracker.record(file_info) {
94-
let _ = app.emit(
95-
"write-source-item-done",
96-
WriteSourceItemDoneEvent {
97-
operation_id: operation_id.to_string(),
98-
source_path: source_path.display().to_string(),
99-
},
100-
);
97+
events.emit_source_item_done(WriteSourceItemDoneEvent {
98+
operation_id: operation_id.to_string(),
99+
source_path: source_path.display().to_string(),
100+
});
101101
}
102102

103103
// Emit progress
104104
if last_progress_time.elapsed() >= state.progress_interval {
105105
let current_file = file_info.path.file_name().map(|n| n.to_string_lossy().to_string());
106-
state.emit_progress_via_app(
107-
app,
106+
state.emit_progress_via_sink(
107+
events,
108108
WriteProgressEvent::new(
109109
operation_id.to_string(),
110110
WriteOperationType::Delete,
@@ -133,15 +133,12 @@ pub(super) fn delete_files_with_progress(
133133
for dir in scan_result.dirs.iter().rev() {
134134
// Check cancellation
135135
if super::state::is_cancelled(&state.intent) {
136-
let _ = app.emit(
137-
"write-cancelled",
138-
WriteCancelledEvent {
139-
operation_id: operation_id.to_string(),
140-
operation_type: WriteOperationType::Delete,
141-
files_processed: files_done,
142-
rolled_back: false, // Delete operations can't be rolled back
143-
},
144-
);
136+
events.emit_cancelled(WriteCancelledEvent {
137+
operation_id: operation_id.to_string(),
138+
operation_type: WriteOperationType::Delete,
139+
files_processed: files_done,
140+
rolled_back: false, // Delete operations can't be rolled back
141+
});
145142
return Err(WriteOperationError::Cancelled {
146143
message: "Operation cancelled by user".to_string(),
147144
});
@@ -155,15 +152,12 @@ pub(super) fn delete_files_with_progress(
155152
spawn_async_sync();
156153

157154
// Emit completion
158-
let _ = app.emit(
159-
"write-complete",
160-
WriteCompleteEvent {
161-
operation_id: operation_id.to_string(),
162-
operation_type: WriteOperationType::Delete,
163-
files_processed: files_done,
164-
bytes_processed: bytes_done,
165-
},
166-
);
155+
events.emit_complete(WriteCompleteEvent {
156+
operation_id: operation_id.to_string(),
157+
operation_type: WriteOperationType::Delete,
158+
files_processed: files_done,
159+
bytes_processed: bytes_done,
160+
});
167161

168162
Ok(())
169163
}
@@ -192,7 +186,7 @@ async fn scan_volume_recursive(
192186
entries: &mut Vec<VolumeDeleteEntry>,
193187
total_bytes: &mut u64,
194188
state: &Arc<WriteOperationState>,
195-
app: &tauri::AppHandle,
189+
events: &dyn OperationEventSink,
196190
operation_id: &str,
197191
last_progress_time: &mut Instant,
198192
) -> Result<(), WriteOperationError> {
@@ -225,7 +219,7 @@ async fn scan_volume_recursive(
225219
entries,
226220
total_bytes,
227221
state,
228-
app,
222+
events,
229223
operation_id,
230224
last_progress_time,
231225
))
@@ -261,8 +255,8 @@ async fn scan_volume_recursive(
261255
if last_progress_time.elapsed() >= state.progress_interval {
262256
let file_count = entries.iter().filter(|e| !e.is_dir).count();
263257
let current_file = path.file_name().map(|n| n.to_string_lossy().to_string());
264-
state.emit_progress_via_app(
265-
app,
258+
state.emit_progress_via_sink(
259+
events,
266260
WriteProgressEvent::new(
267261
operation_id.to_string(),
268262
WriteOperationType::Delete,
@@ -306,8 +300,22 @@ pub(super) async fn delete_volume_files_with_progress(
306300
sources: &[PathBuf],
307301
config: &WriteOperationConfig,
308302
) -> Result<(), WriteOperationError> {
309-
use tauri::Emitter;
303+
let events = TauriEventSink::new(app.clone());
304+
delete_volume_files_with_progress_inner(volume, &events, operation_id, state, sources, config).await
305+
}
310306

307+
#[allow(
308+
clippy::too_many_arguments,
309+
reason = "Matches the parameter pattern of other write operation functions"
310+
)]
311+
pub(super) async fn delete_volume_files_with_progress_inner(
312+
volume: Arc<dyn Volume>,
313+
events: &dyn OperationEventSink,
314+
operation_id: &str,
315+
state: &Arc<WriteOperationState>,
316+
sources: &[PathBuf],
317+
config: &WriteOperationConfig,
318+
) -> Result<(), WriteOperationError> {
311319
// Phase 1: Scan. Recursively enumerate the tree via volume.list_directory().
312320
let mut entries: Vec<VolumeDeleteEntry> = Vec::new();
313321
let mut total_bytes = 0u64;
@@ -324,7 +332,7 @@ pub(super) async fn delete_volume_files_with_progress(
324332
&mut entries,
325333
&mut total_bytes,
326334
state,
327-
app,
335+
events,
328336
operation_id,
329337
&mut last_progress_time,
330338
)
@@ -344,8 +352,8 @@ pub(super) async fn delete_volume_files_with_progress(
344352
let file_count = entries.iter().filter(|e| !e.is_dir).count();
345353

346354
// Emit final scan progress
347-
state.emit_progress_via_app(
348-
app,
355+
state.emit_progress_via_sink(
356+
events,
349357
WriteProgressEvent::new(
350358
operation_id.to_string(),
351359
WriteOperationType::Delete,
@@ -360,17 +368,15 @@ pub(super) async fn delete_volume_files_with_progress(
360368

361369
// Handle dry-run mode
362370
if config.dry_run {
363-
let result = DryRunResult {
371+
events.emit_dry_run_complete(DryRunResult {
364372
operation_id: operation_id.to_string(),
365373
operation_type: WriteOperationType::Delete,
366374
files_total: file_count,
367375
bytes_total: total_bytes,
368376
conflicts_total: 0,
369377
conflicts: Vec::new(),
370378
conflicts_sampled: false,
371-
};
372-
373-
let _ = app.emit("dry-run-complete", result);
379+
});
374380
return Ok(());
375381
}
376382

@@ -384,15 +390,12 @@ pub(super) async fn delete_volume_files_with_progress(
384390
// Delete files
385391
for entry in entries.iter().filter(|e| !e.is_dir) {
386392
if super::state::is_cancelled(&state.intent) {
387-
let _ = app.emit(
388-
"write-cancelled",
389-
WriteCancelledEvent {
390-
operation_id: operation_id.to_string(),
391-
operation_type: WriteOperationType::Delete,
392-
files_processed: files_done,
393-
rolled_back: false,
394-
},
395-
);
393+
events.emit_cancelled(WriteCancelledEvent {
394+
operation_id: operation_id.to_string(),
395+
operation_type: WriteOperationType::Delete,
396+
files_processed: files_done,
397+
rolled_back: false,
398+
});
396399
return Err(WriteOperationError::Cancelled {
397400
message: "Operation cancelled by user".to_string(),
398401
});
@@ -408,8 +411,8 @@ pub(super) async fn delete_volume_files_with_progress(
408411

409412
if last_progress_time.elapsed() >= state.progress_interval {
410413
let current_file = entry.path.file_name().map(|n| n.to_string_lossy().to_string());
411-
state.emit_progress_via_app(
412-
app,
414+
state.emit_progress_via_sink(
415+
events,
413416
WriteProgressEvent::new(
414417
operation_id.to_string(),
415418
WriteOperationType::Delete,
@@ -437,15 +440,12 @@ pub(super) async fn delete_volume_files_with_progress(
437440
// Delete directories (already in deepest-first order from scan_volume_recursive)
438441
for entry in entries.iter().filter(|e| e.is_dir) {
439442
if super::state::is_cancelled(&state.intent) {
440-
let _ = app.emit(
441-
"write-cancelled",
442-
WriteCancelledEvent {
443-
operation_id: operation_id.to_string(),
444-
operation_type: WriteOperationType::Delete,
445-
files_processed: files_done,
446-
rolled_back: false,
447-
},
448-
);
443+
events.emit_cancelled(WriteCancelledEvent {
444+
operation_id: operation_id.to_string(),
445+
operation_type: WriteOperationType::Delete,
446+
files_processed: files_done,
447+
rolled_back: false,
448+
});
449449
return Err(WriteOperationError::Cancelled {
450450
message: "Operation cancelled by user".to_string(),
451451
});
@@ -456,15 +456,12 @@ pub(super) async fn delete_volume_files_with_progress(
456456
}
457457

458458
// Emit completion
459-
let _ = app.emit(
460-
"write-complete",
461-
WriteCompleteEvent {
462-
operation_id: operation_id.to_string(),
463-
operation_type: WriteOperationType::Delete,
464-
files_processed: files_done,
465-
bytes_processed: bytes_done,
466-
},
467-
);
459+
events.emit_complete(WriteCompleteEvent {
460+
operation_id: operation_id.to_string(),
461+
operation_type: WriteOperationType::Delete,
462+
files_processed: files_done,
463+
bytes_processed: bytes_done,
464+
});
468465

469466
Ok(())
470467
}

0 commit comments

Comments
 (0)