1use std::path::{Path, PathBuf};
4
5use cadvm_store::ObjectId;
6use walkdir::WalkDir;
7
8use crate::error::{CoreError, Result};
9use crate::format::CadFormat;
10use crate::ignore::IgnoreList;
11use crate::repo::{Repository, REPO_DIR};
12
13pub fn scan_step_files(repo: &Repository) -> Result<Vec<PathBuf>> {
20 let root = repo.workdir();
21 let ignore = IgnoreList::load(repo)?;
22 let mut files = Vec::new();
23
24 let walker = WalkDir::new(root).into_iter().filter_entry(|entry| {
25 if entry.depth() == 0 {
27 return true;
28 }
29 let name = entry.file_name().to_string_lossy();
30 if entry.file_type().is_dir() {
31 if name == REPO_DIR || name.starts_with('.') {
33 return false;
34 }
35 match entry.path().strip_prefix(root) {
36 Ok(rel) => !ignore.is_ignored(rel),
37 Err(_) => true,
38 }
39 } else {
40 true
41 }
42 });
43
44 for entry in walker {
45 let entry = entry.map_err(|e| {
46 CoreError::io(
47 e.path()
48 .map(Path::to_path_buf)
49 .unwrap_or_else(|| root.to_path_buf()),
50 e.into_io_error()
51 .unwrap_or_else(|| std::io::Error::other("walk error")),
52 )
53 })?;
54 if !entry.file_type().is_file() {
55 continue;
56 }
57 let path = entry.path();
58 if CadFormat::from_path(path).is_none() {
59 continue;
60 }
61 let rel = path.strip_prefix(root).unwrap_or(path).to_path_buf();
62 if ignore.is_ignored(&rel) {
63 continue;
64 }
65 files.push(rel);
66 }
67
68 files.sort();
69 Ok(files)
70}
71
72pub fn abs_path(repo: &Repository, rel: &Path) -> PathBuf {
74 repo.workdir().join(rel)
75}
76
77pub fn read_working_file(repo: &Repository, rel: &Path) -> Result<Vec<u8>> {
79 let path = abs_path(repo, rel);
80 std::fs::read(&path).map_err(|e| CoreError::io(&path, e))
81}
82
83pub fn hash_working_file(repo: &Repository, rel: &Path) -> Result<ObjectId> {
86 let path = abs_path(repo, rel);
87 let file = std::fs::File::open(&path).map_err(|e| CoreError::io(&path, e))?;
88 ObjectId::hash_reader(std::io::BufReader::new(file)).map_err(|e| CoreError::io(&path, e))
89}