diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2015-01-13 20:00:21 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2015-01-13 20:00:21 +0100 |
commit | e973e6f829de5dd1c09d0db39d232230e7eb01d8 (patch) | |
tree | 0a1af5290ee8fc7b53a49ee7014f00bf5c05cadc | |
parent | a2d39529eea4d0ecfcd65a2d245284174cd2e0aa (diff) | |
download | gitpython-e973e6f829de5dd1c09d0db39d232230e7eb01d8.tar.gz |
Added `Repo.merge_base(...)` implementation, including test-case.
Fixes #169
-rw-r--r-- | doc/source/changes.rst | 5 | ||||
-rw-r--r-- | git/repo/base.py | 36 | ||||
-rw-r--r-- | git/test/test_repo.py | 24 |
3 files changed, 63 insertions, 2 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst index a64143c5..e18b07ce 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -2,6 +2,11 @@ Changelog ========= +0.3.6 - Features +================ +* Added `Repo.merge_base()` implementation. See the `respective issue on github <https://github.com/gitpython-developers/GitPython/issues/169>`_ +* A list of all issues can be found here: https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v0.3.6+-+Features%22+ + 0.3.5 - Bugfixes ================ * push/pull/fetch operations will not block anymore diff --git a/git/repo/base.py b/git/repo/base.py index d6efbd58..f5ed2479 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -4,7 +4,11 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php -from git.exc import InvalidGitRepositoryError, NoSuchPathError +from git.exc import ( + InvalidGitRepositoryError, + NoSuchPathError, + GitCommandError +) from git.cmd import ( Git, handle_process_output @@ -456,6 +460,36 @@ class Repo(object): return Commit.iter_items(self, rev, paths, **kwargs) + def merge_base(self, *rev, **kwargs): + """Find the closest common ancestor for the given revision (e.g. Commits, Tags, References, etc). + :param rev: At least two revs to find the common ancestor for. + :param kwargs: Additional arguments to be passed to the repo.git.merge_base() command which does all the work. + :return: A list of Commit objects. If --all was not specified as kwarg, the list will have at max one Commit, + or is empty if no common merge base exists. + :raises ValueError: If not at least two revs are provided + """ + if len(rev) < 2: + raise ValueError("Please specify at least two revs, got only %i" % len(rev)) + # end handle input + + res = list() + try: + lines = self.git.merge_base(*rev, **kwargs).splitlines() + except GitCommandError as err: + if err.status == 128: + raise + # end handle invalid rev + # Status code 1 is returned if there is no merge-base + # (see https://github.com/git/git/blob/master/builtin/merge-base.c#L16) + return res + # end exception handling + + for line in lines: + res.append(self.commit(line)) + # end for each merge-base + + return res + def _get_daemon_export(self): filename = join(self.git_dir, self.DAEMON_EXPORT_FILE) return os.path.exists(filename) diff --git a/git/test/test_repo.py b/git/test/test_repo.py index 046b20a7..a782cefa 100644 --- a/git/test/test_repo.py +++ b/git/test/test_repo.py @@ -27,7 +27,8 @@ from git import ( Submodule, GitCmdObjectDB, Remote, - BadName + BadName, + GitCommandError ) from git.repo.fun import touch from git.util import join_path_native @@ -737,3 +738,24 @@ class TestRepo(TestBase): # Now a branch should be creatable nb = r.create_head('foo') assert nb.is_valid() + + def test_merge_base(self): + repo = self.rorepo + c1 = 'f6aa8d1' + c2 = repo.commit('d46e3fe') + c3 = '763ef75' + self.failUnlessRaises(ValueError, repo.merge_base) + self.failUnlessRaises(ValueError, repo.merge_base, 'foo') + + # two commit merge-base + res = repo.merge_base(c1, c2) + assert isinstance(res, list) and len(res) == 1 and isinstance(res[0], Commit) + assert res[0].hexsha.startswith('3936084') + + for kw in ('a', 'all'): + res = repo.merge_base(c1, c2, c3, **{kw: True}) + assert isinstance(res, list) and len(res) == 1 + # end for eaech keyword signalling all merge-bases to be returned + + # Test for no merge base - can't do as we have + self.failUnlessRaises(GitCommandError, repo.merge_base, c1, 'ffffff') |