1mod template;
19
20use std::fs::read_dir;
21use std::path::{Path, PathBuf};
22use std::rc::Rc;
23
24use anyhow::anyhow;
25use template::LocalFilesystemStorageTemplate;
26use wildland_dfs::storage_backend::StorageBackend;
27use wildland_dfs::unencrypted::StorageBackendFactory;
28use wildland_dfs::Storage;
29
30#[derive(Debug)]
31pub struct LocalFilesystemStorage {
32 base_dir: PathBuf,
33}
34
35impl StorageBackend for LocalFilesystemStorage {
36 fn readdir(&self, path: &Path) -> Result<Vec<PathBuf>, anyhow::Error> {
37 let relative_path = if path.is_absolute() {
38 path.strip_prefix("/").unwrap()
39 } else {
40 path
41 };
42 read_dir(self.base_dir.join(relative_path))
43 .map_err(|e| anyhow!(e))
44 .and_then(|readdir| {
45 readdir
46 .into_iter()
47 .map(|entry_result| {
48 Ok(Path::new("/").join(entry_result?.path().strip_prefix(&self.base_dir)?))
49 })
50 .collect::<Result<Vec<_>, anyhow::Error>>()
51 })
52 }
53}
54
55pub struct LfsBackendFactory {}
56impl StorageBackendFactory for LfsBackendFactory {
57 fn init_backend(&self, storage: Storage) -> Result<Rc<dyn StorageBackend>, anyhow::Error> {
58 let template: LocalFilesystemStorageTemplate =
59 serde_json::from_value(storage.data().clone())?;
60 Ok(Rc::new(LocalFilesystemStorage {
61 base_dir: template.local_dir.join(template.container_prefix),
62 }))
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use std::fs::{create_dir, File};
69 use std::str::FromStr;
70
71 use pretty_assertions::assert_eq;
72 use serde_json::json;
73 use tempdir::TempDir;
74
75 use super::*;
76
77 #[test]
78 fn test_reading_file_in_root_of_lfs_backend() {
79 let tmpdir = TempDir::new("lfs").unwrap(); let storage = Storage::new(
81 Some("Test LFS".to_owned()),
82 "LFS".to_owned(),
83 json!({
84 "local_dir": tmpdir.path(),
85 "container_prefix": "books"
86 }),
87 );
88 let factory = LfsBackendFactory {};
89 let backend = factory.init_backend(storage).unwrap();
90
91 create_dir(tmpdir.path().join("books")).unwrap(); let _ = File::create(tmpdir.path().join("books/file1")).unwrap();
93
94 let files = backend.readdir(Path::new("/")).unwrap();
95
96 assert_eq!(files, vec![PathBuf::from_str("/file1").unwrap()]);
97 }
98 #[test]
99 fn test_reading_file_in_subdir_of_lfs_backend() {
100 let tmpdir = TempDir::new("lfs").unwrap(); let storage = Storage::new(
102 Some("Test LFS".to_owned()),
103 "LFS".to_owned(),
104 json!({
105 "local_dir": tmpdir.path(),
106 "container_prefix": "books"
107 }),
108 );
109 let factory = LfsBackendFactory {};
110 let backend = factory.init_backend(storage).unwrap();
111
112 create_dir(tmpdir.path().join("books")).unwrap(); create_dir(tmpdir.path().join("books").join("dir")).unwrap(); let _ = File::create(tmpdir.path().join("books/dir/file1")).unwrap();
115
116 let files = backend.readdir(Path::new("/dir")).unwrap();
117
118 assert_eq!(files, vec![PathBuf::from_str("/dir/file1").unwrap()]);
119 }
120}