summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Driessen <me@nvie.com>2016-04-14 13:29:33 +0200
committerVincent Driessen <me@nvie.com>2016-04-14 16:11:34 +0200
commit2f1b69ad52670a67e8b766e89451080219871739 (patch)
tree18ab18f42ceeefed7aed1885a525faff9d9b1e34
parent6964e3efc4ac779d458733a05c9d71be2194b2ba (diff)
downloadgitpython-2f1b69ad52670a67e8b766e89451080219871739.tar.gz
Return all available data from git-blame
Returning this now to avoid having to change the function's return value structure later on if we want to emit more information.
-rw-r--r--git/repo/base.py22
-rw-r--r--git/test/test_repo.py11
2 files changed, 25 insertions, 8 deletions
diff --git a/git/repo/base.py b/git/repo/base.py
index f74e0b59..0274c0a7 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -60,12 +60,15 @@ from git.compat import (
import os
import sys
import re
+from collections import namedtuple
DefaultDBType = GitCmdObjectDB
if sys.version_info[:2] < (2, 5): # python 2.4 compatiblity
DefaultDBType = GitCmdObjectDB
# END handle python 2.4
+BlameEntry = namedtuple('BlameEntry', ['commit', 'linenos', 'orig_path', 'orig_linenos'])
+
__all__ = ('Repo', )
@@ -661,10 +664,10 @@ class Repo(object):
"""Iterator for blame information for the given file at the given revision.
Unlike .blame(), this does not return the actual file's contents, only
- a stream of (commit, range) tuples.
+ a stream of BlameEntry tuples.
:parm rev: revision specifier, see git-rev-parse for viable options.
- :return: lazy iterator of (git.Commit, range) tuples, where the commit
+ :return: lazy iterator of BlameEntry tuples, where the commit
indicates the commit to blame for the line, and range
indicates a span of line numbers in the resulting file.
@@ -678,9 +681,10 @@ class Repo(object):
while True:
line = next(stream) # when exhausted, casues a StopIteration, terminating this function
- hexsha, _, lineno, num_lines = line.split()
+ hexsha, orig_lineno, lineno, num_lines = line.split()
lineno = int(lineno)
num_lines = int(num_lines)
+ orig_lineno = int(orig_lineno)
if hexsha not in commits:
# Now read the next few lines and build up a dict of properties
# for this commit
@@ -696,6 +700,7 @@ class Repo(object):
props[tag] = value
if tag == b'filename':
# "filename" formally terminates the entry for --incremental
+ orig_filename = value
break
c = Commit(self, hex_to_bin(hexsha),
@@ -710,9 +715,14 @@ class Repo(object):
else:
# Discard the next line (it's a filename end tag)
line = next(stream)
- assert line.startswith(b'filename'), 'Unexpected git blame output'
-
- yield commits[hexsha], range(lineno, lineno + num_lines)
+ tag, value = line.split(b' ', 1)
+ assert tag == b'filename', 'Unexpected git blame output'
+ orig_filename = value
+
+ yield BlameEntry(commits[hexsha],
+ range(lineno, lineno + num_lines),
+ safe_decode(orig_filename),
+ range(orig_lineno, orig_lineno + num_lines))
def blame(self, rev, file, incremental=False, **kwargs):
"""The blame information for the given file at the given revision.
diff --git a/git/test/test_repo.py b/git/test/test_repo.py
index ab6c502f..d7437d35 100644
--- a/git/test/test_repo.py
+++ b/git/test/test_repo.py
@@ -341,12 +341,19 @@ class TestRepo(TestBase):
assert len(blame_output) == 5
# Check all outputted line numbers
- ranges = flatten([line_numbers for _, line_numbers in blame_output])
+ ranges = flatten([entry.linenos for entry in blame_output])
assert ranges == flatten([range(2, 3), range(14, 15), range(1, 2), range(3, 14), range(15, 17)]), str(ranges)
- commits = [c.hexsha[:7] for c, _ in blame_output]
+ commits = [entry.commit.hexsha[:7] for entry in blame_output]
assert commits == ['82b8902', '82b8902', 'c76852d', 'c76852d', 'c76852d'], str(commits)
+ # Original filenames
+ assert all([entry.orig_path == u'AUTHORS' for entry in blame_output])
+
+ # Original line numbers
+ orig_ranges = flatten([entry.orig_linenos for entry in blame_output])
+ assert orig_ranges == flatten([range(2, 3), range(14, 15), range(1, 2), range(2, 13), range(13, 15)]), str(orig_ranges) # noqa
+
@patch.object(Git, '_call_process')
def test_blame_complex_revision(self, git):
git.return_value = fixture('blame_complex_revision')