changeset_git/repository/
mod.rs1mod commit;
2mod diff;
3mod files;
4mod remote;
5mod staging;
6mod status;
7mod tag;
8
9use std::path::{Path, PathBuf};
10
11use crate::{GitError, Result};
12
13pub struct Repository {
14 pub(crate) inner: git2::Repository,
15 root: PathBuf,
16}
17
18impl Repository {
19 pub fn open(path: &Path) -> Result<Self> {
23 let inner = git2::Repository::discover(path).map_err(|_| GitError::NotARepository {
24 path: path.to_path_buf(),
25 })?;
26
27 let root = inner.workdir().ok_or_else(|| GitError::NotARepository {
28 path: path.to_path_buf(),
29 })?;
30
31 let root = dunce::simplified(root).to_path_buf();
33
34 Ok(Self { inner, root })
35 }
36
37 #[must_use]
38 pub fn root(&self) -> &Path {
39 &self.root
40 }
41
42 pub(crate) fn to_relative_path(&self, path: &Path) -> PathBuf {
43 if path.is_absolute() {
44 let normalized = dunce::simplified(path);
46 normalized
47 .strip_prefix(&self.root)
48 .map_or_else(|_| path.to_path_buf(), Path::to_path_buf)
49 } else {
50 path.to_path_buf()
51 }
52 }
53}
54
55#[cfg(test)]
56pub(crate) mod tests {
57 use super::*;
58 use tempfile::TempDir;
59
60 pub(crate) fn setup_test_repo() -> anyhow::Result<(TempDir, Repository)> {
61 let dir = TempDir::new()?;
62 let repo = git2::Repository::init(dir.path())?;
63
64 let mut config = repo.config()?;
65 config.set_str("user.name", "Test")?;
66 config.set_str("user.email", "test@example.com")?;
67
68 let sig = git2::Signature::now("Test", "test@example.com")?;
69 let tree_id = repo.index()?.write_tree()?;
70 let tree = repo.find_tree(tree_id)?;
71 repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?;
72
73 let repository = Repository::open(dir.path())?;
74 Ok((dir, repository))
75 }
76
77 #[test]
78 fn open_repository() -> anyhow::Result<()> {
79 let (dir, repo) = setup_test_repo()?;
80 let expected = dir.path().canonicalize()?;
81 let actual = repo.root().canonicalize()?;
82 assert_eq!(actual, expected);
83 Ok(())
84 }
85
86 #[test]
87 fn open_nonexistent_repository() {
88 let dir = TempDir::new().expect("failed to create temp dir");
89 let result = Repository::open(dir.path());
90 assert!(matches!(result, Err(GitError::NotARepository { .. })));
91 }
92}