bookdata/layout/
workdir.rs1use std::path::Path;
2use std::{env::current_dir, path::PathBuf};
3
4use anyhow::{anyhow, Result};
5use log::*;
6use relative_path::{RelativePath, RelativePathBuf};
7
8fn is_bookdata_root(path: &Path) -> Result<bool> {
9 let dvc = path.join(".dvc");
10 let config = path.join("config.yaml");
11 if dvc.try_exists()? {
12 debug!("found DVC path at {}", dvc.display());
13 if config.try_exists()? {
14 debug!("found config.yaml at {}", config.display());
15 Ok(true)
16 } else {
17 warn!("found .dvc but not config.yaml, weird directory?");
18 Ok(false)
19 }
20 } else {
21 Ok(false)
22 }
23}
24
25pub fn find_root_relpath() -> Result<RelativePathBuf> {
27 let mut rp = RelativePathBuf::new();
28 let cwd = current_dir()?;
29 debug!("looking for root from working directory {}", cwd.display());
30 loop {
31 let path = rp.to_logical_path(&cwd);
32 debug!("looking for DVC in {}", path.display());
33 if is_bookdata_root(&path)? {
34 info!("found bookdata root at {}", path.display());
35 return Ok(rp);
36 }
37
38 if path.parent().is_some() {
39 rp.push("..");
40 } else {
41 error!("scanned parents and could not find bookdata root");
42 return Err(anyhow!("bookdata not found"));
43 }
44 }
45}
46
47#[allow(dead_code)]
49pub fn find_root_abspath() -> Result<PathBuf> {
50 Ok(find_root_relpath()?.to_path(current_dir()?))
51}
52
53pub fn resolve_path<P: AsRef<RelativePath>>(path: P) -> Result<PathBuf> {
56 let root = find_root_relpath()?;
57 let rrp = root.join_normalized(path.as_ref());
58 let resolved = rrp.to_logical_path(current_dir()?);
59 debug!("resolved {} to {}", path.as_ref(), resolved.display());
60 debug!("root: {}", root);
61 debug!("rrp: {}", rrp);
62 Ok(resolved)
63}
64
65pub fn require_working_root() -> Result<()> {
67 let cwd = current_dir()?;
68 if is_bookdata_root(&cwd)? {
69 Ok(())
70 } else {
71 error!("working directory is not bookdata root");
72 Err(anyhow!("incorrect working directory"))
73 }
74}
75
76pub fn require_working_dir<P: AsRef<Path>>(path: P) -> Result<()> {
78 let path = path.as_ref();
79 let cwd = current_dir()?;
80
81 if !cwd.ends_with(path) {
82 error!("expected to be run in {:?}", path);
83 Err(anyhow!("incorrect working directory"))
84 } else {
85 Ok(())
86 }
87}