1use anyhow::Context;
2use camino::{Utf8Path, Utf8PathBuf};
3use fs_err as fs;
4
5pub use buildfix_fixer_api::RepoView;
7
8#[derive(Debug, Clone)]
10pub struct FsRepoView {
11 root: Utf8PathBuf,
12}
13
14impl FsRepoView {
15 pub fn new(root: Utf8PathBuf) -> Self {
16 Self { root }
17 }
18
19 fn abs(&self, rel: &Utf8Path) -> Utf8PathBuf {
20 if rel.is_absolute() {
21 rel.to_path_buf()
22 } else {
23 self.root.join(rel)
24 }
25 }
26}
27
28impl RepoView for FsRepoView {
29 fn root(&self) -> &Utf8Path {
30 &self.root
31 }
32
33 fn read_to_string(&self, rel: &Utf8Path) -> anyhow::Result<String> {
34 let abs = self.abs(rel);
35 fs::read_to_string(&abs).with_context(|| format!("read {}", abs))
36 }
37
38 fn exists(&self, rel: &Utf8Path) -> bool {
39 self.abs(rel).exists()
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use fs_err as fs;
47 use tempfile::TempDir;
48
49 #[test]
50 fn fs_repo_view_reads_relative_and_absolute_paths() {
51 let temp = TempDir::new().expect("temp dir");
52 let root = Utf8PathBuf::from_path_buf(temp.path().to_path_buf()).expect("utf8");
53 let file_path = root.join("Cargo.toml");
54 fs::write(&file_path, "name = \"demo\"").expect("write");
55
56 let repo = FsRepoView::new(root.clone());
57
58 let rel_contents = repo
59 .read_to_string(Utf8Path::new("Cargo.toml"))
60 .expect("read relative");
61 assert_eq!(rel_contents, "name = \"demo\"");
62
63 assert!(file_path.is_absolute());
64 let abs_contents = repo.read_to_string(&file_path).expect("read absolute");
65 assert_eq!(abs_contents, "name = \"demo\"");
66 }
67
68 #[test]
69 fn fs_repo_view_exists_checks() {
70 let temp = TempDir::new().expect("temp dir");
71 let root = Utf8PathBuf::from_path_buf(temp.path().to_path_buf()).expect("utf8");
72 let file_path = root.join("Cargo.toml");
73 fs::write(&file_path, "name = \"demo\"").expect("write");
74
75 let repo = FsRepoView::new(root);
76 assert!(repo.exists(Utf8Path::new("Cargo.toml")));
77 assert!(!repo.exists(Utf8Path::new("missing.toml")));
78 }
79
80 #[test]
81 fn fs_repo_view_root_is_stable() {
82 let temp = TempDir::new().expect("temp dir");
83 let root = Utf8PathBuf::from_path_buf(temp.path().to_path_buf()).expect("utf8");
84 let repo = FsRepoView::new(root.clone());
85 assert_eq!(repo.root(), root.as_path());
86 }
87}