Skip to content

Commit 73bde1f

Browse files
committed
Merge branch 'add-co-authors'
2 parents 12d91c6 + 72cf71c commit 73bde1f

File tree

5 files changed

+46
-1
lines changed

5 files changed

+46
-1
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ Contributors are:
4848
-Hiroki Tokunaga <tokusan441 _at_ gmail.com>
4949
-Julien Mauroy <pro.julien.mauroy _at_ gmail.com>
5050
-Patrick Gerard
51+
-Luke Twist <[email protected]>
5152
Portions derived from other open source works and are clearly marked.

git/config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
CONDITIONAL_INCLUDE_REGEXP = re.compile(r"(?<=includeIf )\"(gitdir|gitdir/i|onbranch):(.+)\"")
8585

8686

87-
class MetaParserBuilder(abc.ABCMeta):
87+
class MetaParserBuilder(abc.ABCMeta): # noqa: B024
8888
"""Utility class wrapping base-class methods into decorators that assure read-only properties"""
8989

9090
def __new__(cls, name: str, bases: Tuple, clsdict: Dict[str, Any]) -> "MetaParserBuilder":

git/objects/commit.py

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66
import datetime
7+
import re
78
from subprocess import Popen, PIPE
89
from gitdb import IStream
910
from git.util import hex_to_bin, Actor, Stats, finalize_process
@@ -738,3 +739,24 @@ def _deserialize(self, stream: BytesIO) -> "Commit":
738739
return self
739740

740741
# } END serializable implementation
742+
743+
@property
744+
def co_authors(self) -> List[Actor]:
745+
"""
746+
Search the commit message for any co-authors of this commit.
747+
Details on co-authors: https://github.blog/2018-01-29-commit-together-with-co-authors/
748+
749+
:return: List of co-authors for this commit (as Actor objects).
750+
"""
751+
co_authors = []
752+
753+
if self.message:
754+
results = re.findall(
755+
r"^Co-authored-by: (.*) <(.*?)>$",
756+
self.message,
757+
re.MULTILINE,
758+
)
759+
for author in results:
760+
co_authors.append(Actor(*author))
761+
762+
return co_authors

test/test_commit.py

+15
Original file line numberDiff line numberDiff line change
@@ -509,3 +509,18 @@ def test_trailers(self):
509509
assert KEY_1 not in commit.trailers.keys()
510510
assert KEY_2 in commit.trailers.keys()
511511
assert commit.trailers[KEY_2] == VALUE_2
512+
513+
def test_commit_co_authors(self):
514+
commit = copy.copy(self.rorepo.commit("4251bd5"))
515+
commit.message = """Commit message
516+
517+
Co-authored-by: Test User 1 <[email protected]>
518+
Co-authored-by: test_user_2 <[email protected]>
519+
Co_authored_by: test_user_x <[email protected]>
520+
Co-authored-by: test_user_y <[email protected]> text
521+
Co-authored-by: test_user_3 <[email protected]>"""
522+
assert commit.co_authors == [
523+
Actor("Test User 1", "[email protected]"),
524+
Actor("test_user_2", "[email protected]"),
525+
Actor("test_user_3", "[email protected]"),
526+
]

test/test_util.py

+7
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
import os
88
import pickle
9+
import sys
910
import tempfile
1011
import time
1112
from unittest import mock, skipIf
1213
from datetime import datetime
1314

15+
import pytest
1416
import ddt
1517

1618
from git.cmd import dashify
@@ -154,6 +156,11 @@ def test_lock_file(self):
154156
lock_file._obtain_lock_or_raise()
155157
lock_file._release_lock()
156158

159+
@pytest.mark.xfail(
160+
sys.platform == "cygwin",
161+
reason="Cygwin fails here for some reason, always",
162+
raises=AssertionError
163+
)
157164
def test_blocking_lock_file(self):
158165
my_file = tempfile.mktemp()
159166
lock_file = BlockingLockFile(my_file)

0 commit comments

Comments
 (0)