Skip to content

Commit 4315e85

Browse files
committed
Merge pull request #37 from cysp/feature/git_graph
Bind git_graph_* functions
2 parents fa025a6 + 496e6f8 commit 4315e85

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

libgit2-sys/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,15 @@ extern {
18301830
old_tree: *mut git_tree,
18311831
opts: *const git_diff_options)
18321832
-> c_int;
1833+
1834+
pub fn git_graph_ahead_behind(ahead: *mut size_t, behind: *mut size_t,
1835+
repo: *mut git_repository,
1836+
local: *const git_oid, upstream: *const git_oid)
1837+
-> c_int;
1838+
1839+
pub fn git_graph_descendant_of(repo: *mut git_repository,
1840+
commit: *const git_oid, ancestor: *const git_oid)
1841+
-> c_int;
18331842
}
18341843

18351844
#[test]

src/repo.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,35 @@ impl Repository {
10201020
Ok(Oid::from_raw(&raw))
10211021
}
10221022
}
1023+
1024+
/// Count the number of unique commits between two commit objects
1025+
///
1026+
/// There is no need for branches containing the commits to have any
1027+
/// upstream relationship, but it helps to think of one as a branch and the
1028+
/// other as its upstream, the ahead and behind values will be what git
1029+
/// would report for the branches.
1030+
pub fn graph_ahead_behind(&self, local: Oid, upstream: Oid)
1031+
-> Result<(uint, uint), Error> {
1032+
unsafe {
1033+
let mut ahead: size_t = 0;
1034+
let mut behind: size_t = 0;
1035+
try_call!(raw::git_graph_ahead_behind(&mut ahead, &mut behind,
1036+
self.raw(), local.raw(),
1037+
upstream.raw()));
1038+
Ok((ahead as uint, behind as uint))
1039+
}
1040+
}
1041+
1042+
/// Determine if a commit is the descendant of another commit
1043+
pub fn graph_descendant_of(&self, commit: Oid, ancestor: Oid)
1044+
-> Result<bool, Error> {
1045+
unsafe {
1046+
let rv = try_call!(raw::git_graph_descendant_of(self.raw(),
1047+
commit.raw(),
1048+
ancestor.raw()));
1049+
Ok(rv != 0)
1050+
}
1051+
}
10231052
}
10241053

10251054
#[unsafe_destructor]
@@ -1269,4 +1298,49 @@ mod tests {
12691298
let repo = Repository::discover(subdir.path()).unwrap();
12701299
assert!(repo.path() == *td.path());
12711300
}
1301+
1302+
fn graph_repo_init() -> (TempDir, Repository) {
1303+
let (_td, repo) = ::test::repo_init();
1304+
{
1305+
let head = repo.head().unwrap().target().unwrap();
1306+
let head = repo.find_commit(head).unwrap();
1307+
1308+
let mut index = repo.index().unwrap();
1309+
let id = index.write_tree().unwrap();
1310+
1311+
let tree = repo.find_tree(id).unwrap();
1312+
let sig = repo.signature().unwrap();
1313+
repo.commit(Some("HEAD"), &sig, &sig, "second",
1314+
&tree, &[&head]).unwrap();
1315+
}
1316+
(_td, repo)
1317+
}
1318+
1319+
#[test]
1320+
fn smoke_graph_ahead_behind() {
1321+
let (_td, repo) = graph_repo_init();
1322+
let head = repo.head().unwrap().target().unwrap();
1323+
let head = repo.find_commit(head).unwrap();
1324+
let head_id = head.id();
1325+
let head_parent_id = head.parent(0).unwrap().id();
1326+
let (ahead, behind) = repo.graph_ahead_behind(head_id,
1327+
head_parent_id).unwrap();
1328+
assert_eq!(ahead, 1);
1329+
assert_eq!(behind, 0);
1330+
let (ahead, behind) = repo.graph_ahead_behind(head_parent_id,
1331+
head_id).unwrap();
1332+
assert_eq!(ahead, 0);
1333+
assert_eq!(behind, 1);
1334+
}
1335+
1336+
#[test]
1337+
fn smoke_graph_descendant_of() {
1338+
let (_td, repo) = graph_repo_init();
1339+
let head = repo.head().unwrap().target().unwrap();
1340+
let head = repo.find_commit(head).unwrap();
1341+
let head_id = head.id();
1342+
let head_parent_id = head.parent(0).unwrap().id();
1343+
assert!(repo.graph_descendant_of(head_id, head_parent_id).unwrap());
1344+
assert!(!repo.graph_descendant_of(head_parent_id, head_id).unwrap());
1345+
}
12721346
}

0 commit comments

Comments
 (0)