1use crate::{AncestorPath, Config, Git, RootedPath, Utf8Path, Utf8PathBuf};
4use alloc::string::String;
5use core::str::FromStr;
6use dogma::FromPathError;
7use std::{
8 io::{Error, ErrorKind, Result},
9 path::PathBuf,
10};
11
12#[derive(Clone, Debug, Default)]
13pub struct Workspace(pub(crate) RootedPath);
14
15impl FromStr for Workspace {
16 type Err = Error;
17
18 fn from_str(input: &str) -> core::result::Result<Self, Self::Err> {
19 let path = RootedPath::from_str(input)?;
20 if let Some(up) = &path.up
21 && !up.is_dir()
22 {
23 return Err(Error::from(ErrorKind::NotADirectory));
24 }
25 Ok(Self(path))
26 }
27}
28
29impl AsRef<RootedPath> for Workspace {
30 fn as_ref(&self) -> &RootedPath {
31 &self.0
32 }
33}
34
35impl Workspace {
36 pub fn locate() -> Result<Self> {
37 let git = Git::default();
38 let down = git.rev_parse_show_prefix().unwrap(); let up_count = down.components().count();
40 if up_count == 0 {
41 return Ok(Self::default());
42 }
43 let up = AncestorPath::try_from(up_count).ok();
44 Ok(Self(RootedPath { up, down }))
45 }
46
47 pub fn path(&self) -> &RootedPath {
48 &self.0
49 }
50
51 pub fn config(&self) -> Config {
52 Config(self.config_path())
53 }
54
55 pub fn config_path(&self) -> Utf8PathBuf {
56 self.join(".config/readmer")
57 }
58
59 pub fn join(&self, path: impl AsRef<Utf8Path>) -> Utf8PathBuf {
60 self.0.join(path)
61 }
62}