Skip to content

Commit 6657278

Browse files
committed
feat(blame): Support custom rev_opts for blame
The `git blame` CLI offers a repeated `-C` option that can be used to detect lines that move within/between files. While a slower operation, it yields more accurate authorship reports. https://git-scm.com/docs/git-blame#Documentation/git-blame.txt--Cltnumgt While GitPython does enable passing custom kwargs to the command line `git` invocation, the fact that kwargs is a dictionary (i.e. no duplicate keys) means that there was no way to request the `-C` option in `git blame` more than once. This commit adds an optional `rev_opts` parameter to the `blame` method which accepts a list of strings to propagate to the CLI invocation of `git blame`. By using a `List[str]` for `rev_opts`, users of GitPython can pass now the `-C` option multiple times to get more detailed authorship reports from `git blame`.
1 parent 73bde1f commit 6657278

File tree

3 files changed

+11
-3
lines changed

3 files changed

+11
-3
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ Contributors are:
4949
-Julien Mauroy <pro.julien.mauroy _at_ gmail.com>
5050
-Patrick Gerard
5151
-Luke Twist <[email protected]>
52+
-Joseph Hale <me _at_ jhale.dev>
5253
Portions derived from other open source works and are clearly marked.

git/repo/base.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ def blame_incremental(self, rev: str | HEAD, file: str, **kwargs: Any) -> Iterat
950950
)
951951

952952
def blame(
953-
self, rev: Union[str, HEAD], file: str, incremental: bool = False, **kwargs: Any
953+
self, rev: Union[str, HEAD], file: str, incremental: bool = False, rev_opts: Optional[List[str]]=None, **kwargs: Any
954954
) -> List[List[Commit | List[str | bytes] | None]] | Iterator[BlameEntry] | None:
955955
"""The blame information for the given file at the given revision.
956956
@@ -962,8 +962,8 @@ def blame(
962962
of appearance."""
963963
if incremental:
964964
return self.blame_incremental(rev, file, **kwargs)
965-
966-
data: bytes = self.git.blame(rev, "--", file, p=True, stdout_as_string=False, **kwargs)
965+
rev_opts = rev_opts or []
966+
data: bytes = self.git.blame(rev, *rev_opts, "--", file, p=True, stdout_as_string=False, **kwargs)
967967
commits: Dict[str, Commit] = {}
968968
blames: List[List[Commit | List[str | bytes] | None]] = []
969969

test/test_repo.py

+7
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,13 @@ def test_blame_complex_revision(self, git):
553553
self.assertEqual(len(res), 1)
554554
self.assertEqual(len(res[0][1]), 83, "Unexpected amount of parsed blame lines")
555555

556+
@mock.patch.object(Git, "_call_process")
557+
def test_blame_accepts_rev_opts(self, git):
558+
res = self.rorepo.blame("HEAD", "README.md", rev_opts=["-M", "-C", "-C"])
559+
expected_args = ['blame', 'HEAD', '-M', '-C', '-C', '--', 'README.md']
560+
for idx, arg in enumerate(expected_args):
561+
self.assertEqual(git.call_args.args[idx], arg)
562+
556563
@skipIf(
557564
HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
558565
"""FIXME: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute

0 commit comments

Comments
 (0)