Skip to content

Commit

Permalink
Add svn blame support
Browse files Browse the repository at this point in the history
Add new command and add test_blame test case.
  • Loading branch information
hzsunshx authored and idbrii committed Nov 24, 2020
1 parent c0878be commit 0aa2353
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
37 changes: 37 additions & 0 deletions svn/common.py
Expand Up @@ -285,6 +285,43 @@ def export(self, to_path, revision=None, force=False):

self.run_command('export', cmd)

def blame(self, rel_filepath,
revision_from=None, revision_to=None):
"""
svn usage: blame [-r M:N] TARGET[@REV]
"""

full_url_or_path = self.__url_or_path + "/" + rel_filepath

args = []
if revision_from or revision_to:
if not revision_from:
revision_from = '1'

if not revision_to:
revision_to = 'HEAD'

args += ['-r', str(revision_from) + ':' + str(revision_to)]

result = self.run_command(
"blame", args + ["--xml", full_url_or_path], do_combine=True)

root = xml.etree.ElementTree.fromstring(result)

for entry in root.findall("target/entry"):
commit = entry.find("commit")
author = entry.find("commit/author")
date_ = entry.find("commit/date")
if author is None or date_ is None:
continue
info = {
'line_number': int(entry.attrib['line-number']),
"commit_author": self.__element_text(author),
"commit_date": dateutil.parser.parse(date_.text),
"commit_revision": int(commit.attrib["revision"]),
}
yield info

def list(self, extended=False, rel_path=None):
full_url_or_path = self.__url_or_path
if rel_path is not None:
Expand Down
21 changes: 21 additions & 0 deletions svn/resources/README.md
Expand Up @@ -25,6 +25,7 @@ Functions currently implemented:
- update
- cleanup
- remove (i.e. rm, del, delete)
- blame

In addition, there is also an "admin" class (`svn.admin.Admin`) that provides a
`create` method with which to create repositories.
Expand Down Expand Up @@ -268,6 +269,26 @@ for rel_path, e in l.list_recursive():
# 'timestamp': datetime.datetime(2015, 4, 24, 3, 25, 13, 479212, tzinfo=tzutc())}
```

### blame(rel_filepath, revision=None)

Blame specified file.

```
import pprint
import svn.local
lc = svn.local.LocalClient('/tmp/test_repo.co')
for line_info in lc.blame("version.py"):
pprint.pprint(line_info)
# {
# 'line_number': 1,
# 'commit_revision': 1222,
# 'commit_author': 'codeskyblue',
# 'commit_date': datetime.datetime(2018, 12, 20, 3, 25, 13, 479212, tzinfo=tzutc())}
```


### diff_summary(start_revision, end_revision)

Expand Down
16 changes: 16 additions & 0 deletions tests/test_common.py
Expand Up @@ -208,6 +208,22 @@ def test_export(self):
except:
pass

def test_blame(self):
with svn.test_support.temp_common() as (_, _, cc):
f = svn.test_support.populate_bigger_file_change1()
actual_answer = cc.blame(f, revision_to=2)
line1 = next(actual_answer)
for i in range(5):
# find the modified line
line6 = next(actual_answer)
line7 = next(actual_answer)
self.assertEqual(line1['line_number'], 1)
self.assertEqual(line1['commit_revision'], 1)
self.assertEqual(line1['commit_author'], line7['commit_author'])

self.assertEqual(line6['line_number'], 6)
self.assertEqual(line6['commit_revision'], 2)

def test_force__export(self):
with svn.test_support.temp_common() as (_, _, cc):
svn.test_support.populate_bigger_file_changes1()
Expand Down

0 comments on commit 0aa2353

Please sign in to comment.