Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit20a338f

Browse files
committed
Merge pull request#409 from nvie/add-incremental-blame-support
Add incremental blame support
2 parents978eb5b +f533a68 commit20a338f

File tree

4 files changed

+134
-3
lines changed

4 files changed

+134
-3
lines changed

‎git/compat.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# flake8: noqa
99

1010
importsys
11+
importsix
1112

1213
fromgitdb.utils.compatimport (
1314
PY3,
@@ -46,6 +47,20 @@ def mviter(d):
4647
defmviter(d):
4748
returnd.itervalues()
4849

50+
PRE_PY27=sys.version_info< (2,7)
51+
52+
53+
defsafe_decode(s):
54+
"""Safely decodes a binary string to unicode"""
55+
ifisinstance(s,six.text_type):
56+
returns
57+
elifisinstance(s,six.binary_type):
58+
ifPRE_PY27:
59+
returns.decode(defenc)# we're screwed
60+
else:
61+
returns.decode(defenc,errors='replace')
62+
raiseTypeError('Expected bytes or text, but got %r'% (s,))
63+
4964

5065
defwith_metaclass(meta,*bases):
5166
"""copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15"""

‎git/repo/base.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@
5252
fromgit.compatimport (
5353
text_type,
5454
defenc,
55-
PY3
55+
PY3,
56+
safe_decode,
5657
)
5758

5859
importos
5960
importsys
6061
importre
62+
fromsix.movesimportrange
6163

6264
DefaultDBType=GitCmdObjectDB
6365
ifsys.version_info[:2]< (2,5):# python 2.4 compatiblity
@@ -655,7 +657,64 @@ def active_branch(self):
655657
:return: Head to the active branch"""
656658
returnself.head.reference
657659

658-
defblame(self,rev,file):
660+
defblame_incremental(self,rev,file,**kwargs):
661+
"""Iterator for blame information for the given file at the given revision.
662+
663+
Unlike .blame(), this does not return the actual file's contents, only
664+
a stream of (commit, range) tuples.
665+
666+
:parm rev: revision specifier, see git-rev-parse for viable options.
667+
:return: lazy iterator of (git.Commit, range) tuples, where the commit
668+
indicates the commit to blame for the line, and range
669+
indicates a span of line numbers in the resulting file.
670+
671+
If you combine all line number ranges outputted by this command, you
672+
should get a continuous range spanning all line numbers in the file.
673+
"""
674+
data=self.git.blame(rev,'--',file,p=True,incremental=True,stdout_as_string=False,**kwargs)
675+
commits=dict()
676+
677+
stream=iter(data.splitlines())
678+
whileTrue:
679+
line=next(stream)# when exhausted, casues a StopIteration, terminating this function
680+
681+
hexsha,_,lineno,num_lines=line.split()
682+
lineno=int(lineno)
683+
num_lines=int(num_lines)
684+
ifhexshanotincommits:
685+
# Now read the next few lines and build up a dict of properties
686+
# for this commit
687+
props=dict()
688+
whileTrue:
689+
line=next(stream)
690+
ifline==b'boundary':
691+
# "boundary" indicates a root commit and occurs
692+
# instead of the "previous" tag
693+
continue
694+
695+
tag,value=line.split(b' ',1)
696+
props[tag]=value
697+
iftag==b'filename':
698+
# "filename" formally terminates the entry for --incremental
699+
break
700+
701+
c=Commit(self,hex_to_bin(hexsha),
702+
author=Actor(safe_decode(props[b'author']),
703+
safe_decode(props[b'author-mail'].lstrip(b'<').rstrip(b'>'))),
704+
authored_date=int(props[b'author-time']),
705+
committer=Actor(safe_decode(props[b'committer']),
706+
safe_decode(props[b'committer-mail'].lstrip(b'<').rstrip(b'>'))),
707+
committed_date=int(props[b'committer-time']),
708+
message=safe_decode(props[b'summary']))
709+
commits[hexsha]=c
710+
else:
711+
# Discard the next line (it's a filename end tag)
712+
line=next(stream)
713+
assertline.startswith(b'filename'),'Unexpected git blame output'
714+
715+
yieldcommits[hexsha],range(lineno,lineno+num_lines)
716+
717+
defblame(self,rev,file,incremental=False,**kwargs):
659718
"""The blame information for the given file at the given revision.
660719
661720
:parm rev: revision specifier, see git-rev-parse for viable options.
@@ -664,7 +723,10 @@ def blame(self, rev, file):
664723
A list of tuples associating a Commit object with a list of lines that
665724
changed within the given commit. The Commit objects will be given in order
666725
of appearance."""
667-
data=self.git.blame(rev,'--',file,p=True,stdout_as_string=False)
726+
ifincremental:
727+
returnself.blame_incremental(rev,file,**kwargs)
728+
729+
data=self.git.blame(rev,'--',file,p=True,stdout_as_string=False,**kwargs)
668730
commits=dict()
669731
blames=list()
670732
info=None

‎git/test/fixtures/blame_incremental

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
82b8902e033430000481eb355733cd7065342037 2 2 1
2+
author Sebastian Thiel
3+
author-mail <byronimo@gmail.com>
4+
author-time 1270634931
5+
author-tz +0200
6+
committer Sebastian Thiel
7+
committer-mail <byronimo@gmail.com>
8+
committer-time 1270634931
9+
committer-tz +0200
10+
summary Used this release for a first beta of the 0.2 branch of development
11+
previous 501bf602abea7d21c3dbb409b435976e92033145 AUTHORS
12+
filename AUTHORS
13+
82b8902e033430000481eb355733cd7065342037 14 14 1
14+
filename AUTHORS
15+
c76852d0bff115720af3f27acdb084c59361e5f6 1 1 1
16+
author Michael Trier
17+
author-mail <mtrier@gmail.com>
18+
author-time 1232829627
19+
author-tz -0500
20+
committer Michael Trier
21+
committer-mail <mtrier@gmail.com>
22+
committer-time 1232829627
23+
committer-tz -0500
24+
summary Lots of spring cleaning and added in Sphinx documentation.
25+
previous bcd57e349c08bd7f076f8d6d2f39b702015358c1 AUTHORS
26+
filename AUTHORS
27+
c76852d0bff115720af3f27acdb084c59361e5f6 2 3 11
28+
filename AUTHORS
29+
c76852d0bff115720af3f27acdb084c59361e5f6 13 15 2
30+
filename AUTHORS

‎git/test/test_repo.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@
5050
fromnoseimportSkipTest
5151

5252

53+
defiter_flatten(lol):
54+
foritemsinlol:
55+
foriteminitems:
56+
yielditem
57+
58+
59+
defflatten(lol):
60+
returnlist(iter_flatten(lol))
61+
62+
5363
classTestRepo(TestBase):
5464

5565
@raises(InvalidGitRepositoryError)
@@ -323,6 +333,20 @@ def test_blame_real(self):
323333
assertc,"Should have executed at least one blame command"
324334
assertnml,"There should at least be one blame commit that contains multiple lines"
325335

336+
@patch.object(Git,'_call_process')
337+
deftest_blame_incremental(self,git):
338+
git.return_value=fixture('blame_incremental')
339+
blame_output=self.rorepo.blame_incremental('9debf6b0aafb6f7781ea9d1383c86939a1aacde3','AUTHORS')
340+
blame_output=list(blame_output)
341+
assertlen(blame_output)==5
342+
343+
# Check all outputted line numbers
344+
ranges=flatten([line_numbersfor_,line_numbersinblame_output])
345+
assertranges==flatten([range(2,3),range(14,15),range(1,2),range(3,14),range(15,17)]),str(ranges)
346+
347+
commits= [c.hexsha[:7]forc,_inblame_output]
348+
assertcommits== ['82b8902','82b8902','c76852d','c76852d','c76852d'],str(commits)
349+
326350
@patch.object(Git,'_call_process')
327351
deftest_blame_complex_revision(self,git):
328352
git.return_value=fixture('blame_complex_revision')

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp