rusync/workers/
sync_worker.rs1use std::fs;
2use std::path::Path;
3use std::path::PathBuf;
4use std::sync::mpsc::{Receiver, Sender};
5
6use anyhow::{Context, Error};
7
8use crate::entry::Entry;
9use crate::fsops;
10use crate::fsops::SyncOutcome;
11use crate::progress::ProgressMessage;
12use crate::sync::SyncOptions;
13
14pub struct SyncWorker {
15 input: Receiver<Entry>,
16 output: Sender<ProgressMessage>,
17 source: PathBuf,
18 destination: PathBuf,
19}
20
21impl SyncWorker {
22 pub fn new(
23 source: &Path,
24 destination: &Path,
25 input: Receiver<Entry>,
26 output: Sender<ProgressMessage>,
27 ) -> SyncWorker {
28 SyncWorker {
29 source: source.to_path_buf(),
30 destination: destination.to_path_buf(),
31 input,
32 output,
33 }
34 }
35
36 pub fn start(self, opts: SyncOptions) -> Result<(), Error> {
37 for entry in self.input.iter() {
38 let sync_outcome = self.sync(&entry, opts);
39 let progress_message = match sync_outcome {
40 Ok(s) => ProgressMessage::DoneSyncing(s),
41 Err(e) => ProgressMessage::SyncError {
42 entry: entry.description().to_string(),
43 details: format!("{:#}", e),
44 },
45 };
46 self.output.send(progress_message)?;
47 }
48 Ok(())
49 }
50
51 fn create_missing_dest_dirs(&self, rel_path: &Path) -> Result<(), Error> {
52 let parent_rel_path = rel_path
53 .parent()
54 .expect("dest directory should have a parent");
55 let to_create = self.destination.join(parent_rel_path);
56 fs::create_dir_all(&to_create)
57 .with_context(|| format!("Could not create '{}'", to_create.display()))?;
58 Ok(())
59 }
60
61 fn sync(&self, src_entry: &Entry, opts: SyncOptions) -> Result<SyncOutcome, Error> {
62 let rel_path = fsops::get_rel_path(src_entry.path(), &self.source);
63 self.create_missing_dest_dirs(&rel_path)?;
64 let desc = rel_path.to_string_lossy();
65
66 let dest_path = self.destination.join(&rel_path);
67 let dest_entry = Entry::new(&desc, &dest_path);
68 let outcome = fsops::sync_entries(&self.output, src_entry, &dest_entry)?;
69 #[cfg(unix)]
70 {
71 if opts.preserve_permissions {
72 fsops::copy_permissions(src_entry, &dest_entry)?;
73 }
74 }
75 Ok(outcome)
76 }
77}