From 4709cae1a1b8c7a8b0729eb4dac2abfd4a23d28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 28 Aug 2014 13:51:40 +0200 Subject: [PATCH] Add Repository.ahead_behind() This lets us ask how many diverging commits each side of two histories have. --- docs/repository.rst | 4 ++++ pygit2/decl.h | 1 + pygit2/repository.py | 38 ++++++++++++++++++++++++++++++++++++++ test/test_repository.py | 11 +++++++++++ 4 files changed, 54 insertions(+) diff --git a/docs/repository.rst b/docs/repository.rst index ce8af39..5f5850a 100644 --- a/docs/repository.rst +++ b/docs/repository.rst @@ -69,4 +69,8 @@ Below there are some general attributes and methods: .. automethod:: pygit2.Repository.write .. automethod:: pygit2.Repository.reset .. automethod:: pygit2.Repository.state_cleanup +<<<<<<< HEAD .. automethod:: pygit2.Repository.write_archive +======= +.. automethod:: pygit2.Repository.ahead_behind +>>>>>>> Add Repsitory.ahead_behind() diff --git a/pygit2/decl.h b/pygit2/decl.h index c628e66..5c0dda4 100644 --- a/pygit2/decl.h +++ b/pygit2/decl.h @@ -535,6 +535,7 @@ int git_repository_init_ext( int git_repository_set_head(git_repository *repo, const char *refname, const git_signature *signature, const char *log_message); int git_repository_set_head_detached(git_repository *repo, const git_oid *commitish, const git_signature *signature, const char *log_message); +int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream); /* * git_index diff --git a/pygit2/repository.py b/pygit2/repository.py index 3dd14f1..064ebb9 100644 --- a/pygit2/repository.py +++ b/pygit2/repository.py @@ -625,3 +625,41 @@ class Repository(_Repository): info.mode = 0o777 # symlinks get placeholder archive.addfile(info, StringIO(content)) + + # + # Ahead-behind, which mostly lives on its own namespace + # + def ahead_behind(self, local, upstream): + """ahead_behind(local, upstream) -> (int, int) + + Calculate how many different commits are in the non-common parts + of the history between the two given ids. + + Ahead is how many commits are in the ancestry of the 'local' + commit which are not in the 'upstream' commit. Behind is the + opposite. + + Arguments + + local + The commit which is considered the local or current state + upstream + The commit which is considered the upstream + + Returns a tuple with the number of commits ahead and behind respectively. + """ + + if not isinstance(local, Oid): + local = self.expand_id(local) + + if not isinstance(upstream, Oid): + upstream = self.expand_id(upstream) + + ahead, behind = ffi.new('size_t*'), ffi.new('size_t*') + oid1, oid2 = ffi.new('git_oid *'), ffi.new('git_oid *') + ffi.buffer(oid1)[:] = local.raw[:] + ffi.buffer(oid2)[:] = upstream.raw[:] + err = C.git_graph_ahead_behind(ahead, behind, self._repo, oid1, oid2) + check_error(err) + + return int(ahead[0]), int(behind[0]) diff --git a/test/test_repository.py b/test/test_repository.py index cb032fa..88fbb04 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -300,6 +300,17 @@ class RepositoryTest_II(utils.RepoTestCase): self.assertEqual(commit.hex, 'acecd5ea2924a4b900e7e149496e1f4b57976e51') + def test_ahead_behind(self): + ahead, behind = self.repo.ahead_behind('5ebeeebb320790caf276b9fc8b24546d63316533', + '4ec4389a8068641da2d6578db0419484972284c8') + self.assertEqual(1, ahead) + self.assertEqual(2, behind) + + ahead, behind = self.repo.ahead_behind('4ec4389a8068641da2d6578db0419484972284c8', + '5ebeeebb320790caf276b9fc8b24546d63316533') + self.assertEqual(2, ahead) + self.assertEqual(1, behind) + def test_reset_hard(self): ref = "5ebeeebb320790caf276b9fc8b24546d63316533" with open(os.path.join(self.repo.workdir, "hello.txt")) as f: