Skip to main content

ephemeris_files/path/
repository_root.rs

1use std::path::{Path, PathBuf};
2
3use super::{PathError, RepositoryPath};
4use crate::FilesError;
5
6/// A canonical repository root directory.
7///
8/// The only constructor canonicalizes the path, so every value holds an
9/// absolute path with no symlinks in it.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct RepositoryRoot(PathBuf);
12
13impl RepositoryRoot {
14    /// Canonicalize `path` into a repository root.
15    ///
16    /// # Errors
17    /// Returns an error when the path does not exist or cannot be read.
18    pub fn new(path: &Path) -> Result<Self, PathError> {
19        path.canonicalize()
20            .map(Self)
21            .map_err(|source| PathError::Io {
22                path: path.to_path_buf(),
23                source,
24            })
25    }
26
27    /// The root of the work tree that holds `start`, found by searching
28    /// upwards.
29    ///
30    /// # Errors
31    /// Returns an error when `start` is not inside a repository with a work
32    /// tree.
33    pub fn discover(start: &Path) -> Result<Self, FilesError> {
34        let repository = git2::Repository::discover(start).map_err(|source| FilesError::Open {
35            path: start.to_path_buf(),
36            source,
37        })?;
38        let work_tree = repository.workdir().ok_or(FilesError::NoWorktree)?;
39        Ok(Self::new(work_tree)?)
40    }
41
42    /// The canonical absolute path.
43    #[must_use]
44    pub fn as_path(&self) -> &Path {
45        &self.0
46    }
47
48    /// The repository-relative form of an absolute path below this root.
49    ///
50    /// # Errors
51    /// Returns an error when `path` is not below the root or is not a valid
52    /// repository path.
53    pub fn relative(&self, path: &Path) -> Result<RepositoryPath, PathError> {
54        let relative = path
55            .strip_prefix(&self.0)
56            .map_err(|_outside| PathError::Outside(path.to_path_buf()))?;
57        RepositoryPath::try_from(relative)
58    }
59}