|
4 | 4 | # This module is part of GitPython and is released under
|
5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php
|
6 | 6 |
|
7 |
| -from git.exc import InvalidGitRepositoryError, NoSuchPathError |
| 7 | +from git.exc import ( |
| 8 | + InvalidGitRepositoryError, |
| 9 | + NoSuchPathError, |
| 10 | + GitCommandError |
| 11 | +) |
8 | 12 | from git.cmd import (
|
9 | 13 | Git,
|
10 | 14 | handle_process_output
|
@@ -456,6 +460,36 @@ def iter_commits(self, rev=None, paths='', **kwargs):
|
456 | 460 |
|
457 | 461 | return Commit.iter_items(self, rev, paths, **kwargs)
|
458 | 462 |
|
| 463 | + def merge_base(self, *rev, **kwargs): |
| 464 | + """Find the closest common ancestor for the given revision (e.g. Commits, Tags, References, etc). |
| 465 | + :param rev: At least two revs to find the common ancestor for. |
| 466 | + :param kwargs: Additional arguments to be passed to the repo.git.merge_base() command which does all the work. |
| 467 | + :return: A list of Commit objects. If --all was not specified as kwarg, the list will have at max one Commit, |
| 468 | + or is empty if no common merge base exists. |
| 469 | + :raises ValueError: If not at least two revs are provided |
| 470 | + """ |
| 471 | + if len(rev) < 2: |
| 472 | + raise ValueError("Please specify at least two revs, got only %i" % len(rev)) |
| 473 | + # end handle input |
| 474 | + |
| 475 | + res = list() |
| 476 | + try: |
| 477 | + lines = self.git.merge_base(*rev, **kwargs).splitlines() |
| 478 | + except GitCommandError as err: |
| 479 | + if err.status == 128: |
| 480 | + raise |
| 481 | + # end handle invalid rev |
| 482 | + # Status code 1 is returned if there is no merge-base |
| 483 | + # (see https://github.com/git/git/blob/master/builtin/merge-base.c#L16) |
| 484 | + return res |
| 485 | + # end exception handling |
| 486 | + |
| 487 | + for line in lines: |
| 488 | + res.append(self.commit(line)) |
| 489 | + # end for each merge-base |
| 490 | + |
| 491 | + return res |
| 492 | + |
459 | 493 | def _get_daemon_export(self):
|
460 | 494 | filename = join(self.git_dir, self.DAEMON_EXPORT_FILE)
|
461 | 495 | return os.path.exists(filename)
|
|
0 commit comments