possum/
dir.rs

1use std::borrow::Borrow;
2
3use super::*;
4
5#[derive(Clone, Debug)]
6pub struct Dir {
7    path_buf: PathBuf,
8    block_size: u64,
9    supports_file_cloning: bool,
10}
11
12impl AsRef<Path> for Dir {
13    fn as_ref(&self) -> &Path {
14        &self.path_buf
15    }
16}
17
18impl Borrow<Path> for Dir {
19    fn borrow(&self) -> &Path {
20        &self.path_buf
21    }
22}
23
24impl Dir {
25    pub fn new(path_buf: PathBuf) -> Result<Self> {
26        fs::create_dir_all(&path_buf)?;
27        let block_size = path_min_hole_size(&path_buf)?;
28        let file = open_dir_as_file(&path_buf)?;
29        let supports_file_cloning_flag = file.file_system_flags()?.supports_block_cloning();
30        let supports_file_cloning = match supports_file_cloning_flag {
31            Some(some) => some,
32            None => {
33                let src = tempfile::NamedTempFile::new_in(&path_buf)?;
34                let dst_path = random_file_name_in_dir(&path_buf, ".clone_test-");
35                assert!(!dst_path.exists());
36                let clone_res = clonefile(src.path(), &dst_path);
37                let _ = std::fs::remove_file(&dst_path);
38                match clone_res {
39                    Ok(()) => true,
40                    Err(err) if CloneFileError::is_unsupported(&err) => {
41                        warn!(?err, "clonefile unsupported");
42                        false
43                    }
44                    Err(err) => {
45                        error!(?err);
46                        return Err(err).context("testing clonefile");
47                    }
48                }
49            }
50        };
51        Ok(Self {
52            path_buf,
53            block_size,
54            supports_file_cloning,
55        })
56    }
57
58    pub fn path(&self) -> &Path {
59        &self.path_buf
60    }
61
62    pub fn block_size(&self) -> u64 {
63        self.block_size
64    }
65
66    pub fn supports_file_cloning(&self) -> bool {
67        self.supports_file_cloning
68    }
69
70    /// Walks the underlying files in the possum directory.
71    pub fn walk_dir(&self) -> Result<Vec<walk::Entry>> {
72        crate::walk::walk_dir(self)
73    }
74}