diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f7175f4140..0909d15994 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2148,6 +2148,7 @@ extern "C" { pub fn git_repository_is_empty(repo: *mut git_repository) -> c_int; pub fn git_repository_is_shallow(repo: *mut git_repository) -> c_int; pub fn git_repository_path(repo: *const git_repository) -> *const c_char; + pub fn git_repository_commondir(repo: *const git_repository) -> *const c_char; pub fn git_repository_state(repo: *mut git_repository) -> c_int; pub fn git_repository_workdir(repo: *const git_repository) -> *const c_char; pub fn git_repository_set_workdir( diff --git a/src/repo.rs b/src/repo.rs index b94b4007db..3924b2aa14 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -456,6 +456,18 @@ impl Repository { } } + /// Returns the path of the shared common directory for this repository. + /// + /// If the repository is bare, it is the root directory for the repository. + /// If the repository is a worktree, it is the parent repo's gitdir. + /// Otherwise, it is the gitdir. + pub fn commondir(&self) -> &Path { + unsafe { + let ptr = raw::git_repository_commondir(self.raw); + util::bytes2path(crate::opt_bytes(self, ptr).unwrap()) + } + } + /// Returns the current state of this repository pub fn state(&self) -> RepositoryState { let state = unsafe { raw::git_repository_state(self.raw) }; @@ -4304,4 +4316,22 @@ Committer Name "#, .unwrap(); assert_eq!(tag.id(), found_tag.id()); } + + #[test] + fn smoke_commondir() { + let (td, repo) = crate::test::repo_init(); + assert_eq!( + crate::test::realpath(repo.path()).unwrap(), + crate::test::realpath(repo.commondir()).unwrap() + ); + + let worktree = repo + .worktree("test", &td.path().join("worktree"), None) + .unwrap(); + let worktree_repo = Repository::open_from_worktree(&worktree).unwrap(); + assert_eq!( + crate::test::realpath(repo.path()).unwrap(), + crate::test::realpath(worktree_repo.commondir()).unwrap() + ); + } }