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();
32
33 Ok(Self { inner, root })
34 }
35
36 #[must_use]
37 pub fn root(&self) -> &Path {
38 &self.root
39 }
40
41 pub(crate) fn to_relative_path(&self, path: &Path) -> PathBuf {
42 if path.is_absolute() {
43 let normalized = dunce::simplified(path);
44 normalized
45 .strip_prefix(&self.root)
46 .map_or_else(|_| path.to_path_buf(), Path::to_path_buf)
47 } else {
48 path.to_path_buf()
49 }
50 }
51}
52
53#[cfg(test)]
54pub(crate) mod tests {
55 use super::*;
56 use tempfile::TempDir;
57
58 pub(crate) fn setup_test_repo() -> anyhow::Result<(TempDir, Repository)> {
59 let dir = TempDir::new()?;
60 let repo = git2::Repository::init(dir.path())?;
61
62 let mut config = repo.config()?;
63 config.set_str("user.name", "Test")?;
64 config.set_str("user.email", "test@example.com")?;
65
66 let sig = git2::Signature::now("Test", "test@example.com")?;
67 let tree_id = repo.index()?.write_tree()?;
68 let tree = repo.find_tree(tree_id)?;
69 repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?;
70
71 let repository = Repository::open(dir.path())?;
72 Ok((dir, repository))
73 }
74
75 #[test]
76 fn open_repository() -> anyhow::Result<()> {
77 let (dir, repo) = setup_test_repo()?;
78 let expected = dir.path().canonicalize()?;
79 let actual = repo.root().canonicalize()?;
80 assert_eq!(actual, expected);
81 Ok(())
82 }
83
84 #[test]
85 fn open_nonexistent_repository() {
86 let dir = TempDir::new().expect("failed to create temp dir");
87 let result = Repository::open(dir.path());
88 assert!(matches!(result, Err(GitError::NotARepository { .. })));
89 }
90}