git: replaced some raw subprocess commands with dedicated GIT vcsserver commands.
This commit is contained in:
parent
3167ea3c86
commit
5b07354763
5 changed files with 38 additions and 91 deletions
|
|
@ -223,17 +223,9 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
Returns list of child commits.
|
||||
"""
|
||||
rev_filter = settings.GIT_REV_FILTER
|
||||
output, __ = self.repository.run_git_command(
|
||||
['rev-list', '--children'] + rev_filter)
|
||||
|
||||
child_ids = []
|
||||
pat = re.compile(r'^%s' % self.raw_id)
|
||||
for l in output.splitlines():
|
||||
if pat.match(l):
|
||||
found_ids = l.split(' ')[1:]
|
||||
child_ids.extend(found_ids)
|
||||
return self._make_commits(child_ids)
|
||||
children = self._remote.children(self.raw_id)
|
||||
return self._make_commits(children)
|
||||
|
||||
def _make_commits(self, commit_ids):
|
||||
def commit_maker(_commit_id):
|
||||
|
|
@ -271,52 +263,27 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
Returns history of file as reversed list of `GitCommit` objects for
|
||||
which file at given `path` has been modified.
|
||||
|
||||
TODO: This function now uses an underlying 'git' command which works
|
||||
quickly but ideally we should replace with an algorithm.
|
||||
"""
|
||||
self._get_filectx(path)
|
||||
f_path = safe_str(path)
|
||||
|
||||
# optimize for n==1, rev-list is much faster for that use-case
|
||||
if limit == 1:
|
||||
cmd = ['rev-list', '-1', self.raw_id, '--', f_path]
|
||||
else:
|
||||
cmd = ['log']
|
||||
if limit:
|
||||
cmd.extend(['-n', str(safe_int(limit, 0))])
|
||||
cmd.extend(['--pretty=format: %H', '-s', self.raw_id, '--', f_path])
|
||||
|
||||
output, __ = self.repository.run_git_command(cmd)
|
||||
commit_ids = re.findall(r'[0-9a-fA-F]{40}', output)
|
||||
|
||||
path = self._get_filectx(path)
|
||||
hist = self._remote.node_history(self.raw_id, path, limit)
|
||||
return [
|
||||
self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
|
||||
for commit_id in commit_ids]
|
||||
for commit_id in hist]
|
||||
|
||||
def get_file_annotate(self, path, pre_load=None):
|
||||
"""
|
||||
Returns a generator of four element tuples with
|
||||
lineno, commit_id, commit lazy loader and line
|
||||
|
||||
TODO: This function now uses os underlying 'git' command which is
|
||||
generally not good. Should be replaced with algorithm iterating
|
||||
commits.
|
||||
"""
|
||||
cmd = ['blame', '-l', '--root', '-r', self.raw_id, '--', path]
|
||||
# -l ==> outputs long shas (and we need all 40 characters)
|
||||
# --root ==> doesn't put '^' character for bounderies
|
||||
# -r commit_id ==> blames for the given commit
|
||||
output, __ = self.repository.run_git_command(cmd)
|
||||
|
||||
for i, blame_line in enumerate(output.split('\n')[:-1]):
|
||||
line_no = i + 1
|
||||
commit_id, line = re.split(r' ', blame_line, 1)
|
||||
result = self._remote.node_annotate(self.raw_id, path)
|
||||
|
||||
for ln_no, commit_id, content in result:
|
||||
yield (
|
||||
line_no, commit_id,
|
||||
lambda: self.repository.get_commit(commit_id=commit_id,
|
||||
pre_load=pre_load),
|
||||
line)
|
||||
ln_no, commit_id,
|
||||
lambda: self.repository.get_commit(commit_id=commit_id, pre_load=pre_load),
|
||||
content)
|
||||
|
||||
def get_nodes(self, path):
|
||||
|
||||
|
|
|
|||
|
|
@ -549,33 +549,16 @@ class GitRepository(BaseRepository):
|
|||
if path1 is not None and path1 != path:
|
||||
raise ValueError("Diff of two different paths not supported.")
|
||||
|
||||
flags = [
|
||||
'-U%s' % context, '--full-index', '--binary', '-p',
|
||||
'-M', '--abbrev=40']
|
||||
if ignore_whitespace:
|
||||
flags.append('-w')
|
||||
|
||||
if commit1 == self.EMPTY_COMMIT:
|
||||
cmd = ['show'] + flags + [commit2.raw_id]
|
||||
else:
|
||||
cmd = ['diff'] + flags + [commit1.raw_id, commit2.raw_id]
|
||||
|
||||
if path:
|
||||
cmd.extend(['--', path])
|
||||
file_filter = path
|
||||
else:
|
||||
file_filter = None
|
||||
|
||||
stdout, __ = self.run_git_command(cmd)
|
||||
# If we used 'show' command, strip first few lines (until actual diff
|
||||
# starts)
|
||||
if commit1 == self.EMPTY_COMMIT:
|
||||
lines = stdout.splitlines()
|
||||
x = 0
|
||||
for line in lines:
|
||||
if line.startswith('diff'):
|
||||
break
|
||||
x += 1
|
||||
# Append new line just like 'diff' command do
|
||||
stdout = '\n'.join(lines[x:]) + '\n'
|
||||
return GitDiff(stdout)
|
||||
diff = self._remote.diff(
|
||||
commit1.raw_id, commit2.raw_id, file_filter=file_filter,
|
||||
opt_ignorews=ignore_whitespace,
|
||||
context=context)
|
||||
return GitDiff(diff)
|
||||
|
||||
def strip(self, commit_id, branch_name):
|
||||
commit = self.get_commit(commit_id=commit_id)
|
||||
|
|
|
|||
|
|
@ -266,8 +266,7 @@ class MercurialCommit(base.BaseCommit):
|
|||
for ln_no, commit_id, content in result:
|
||||
yield (
|
||||
ln_no, commit_id,
|
||||
lambda: self.repository.get_commit(commit_id=commit_id,
|
||||
pre_load=pre_load),
|
||||
lambda: self.repository.get_commit(commit_id=commit_id, pre_load=pre_load),
|
||||
content)
|
||||
|
||||
def get_nodes(self, path):
|
||||
|
|
|
|||
|
|
@ -1065,37 +1065,35 @@ class TestGitSpecificWithRepo(BackendTestMixin):
|
|||
|
||||
def test_paths_fast_traversing(self):
|
||||
commit = self.repo.get_commit()
|
||||
assert (
|
||||
commit.get_node('foobar/static/js/admin/base.js').content ==
|
||||
'base')
|
||||
assert commit.get_node('foobar/static/js/admin/base.js').content == 'base'
|
||||
|
||||
def test_get_diff_runs_git_command_with_hashes(self):
|
||||
comm1 = self.repo[0]
|
||||
comm2 = self.repo[1]
|
||||
self.repo.run_git_command = mock.Mock(return_value=['', ''])
|
||||
self.repo.get_diff(comm1, comm2)
|
||||
|
||||
self.repo.run_git_command.assert_called_once_with(
|
||||
['diff', '-U3', '--full-index', '--binary', '-p', '-M',
|
||||
'--abbrev=40', comm1.raw_id, comm2.raw_id])
|
||||
with mock.patch.object(self.repo, '_remote') as remote_mock:
|
||||
self.repo.get_diff(comm1, comm2)
|
||||
|
||||
remote_mock.diff.assert_called_once_with(
|
||||
comm1.raw_id, comm2.raw_id,
|
||||
file_filter=None, opt_ignorews=False, context=3)
|
||||
|
||||
def test_get_diff_runs_git_command_with_str_hashes(self):
|
||||
comm2 = self.repo[1]
|
||||
self.repo.run_git_command = mock.Mock(return_value=['', ''])
|
||||
self.repo.get_diff(self.repo.EMPTY_COMMIT, comm2)
|
||||
self.repo.run_git_command.assert_called_once_with(
|
||||
['show', '-U3', '--full-index', '--binary', '-p', '-M',
|
||||
'--abbrev=40', comm2.raw_id])
|
||||
with mock.patch.object(self.repo, '_remote') as remote_mock:
|
||||
self.repo.get_diff(self.repo.EMPTY_COMMIT, comm2)
|
||||
remote_mock.diff.assert_called_once_with(
|
||||
self.repo.EMPTY_COMMIT.raw_id, comm2.raw_id,
|
||||
file_filter=None, opt_ignorews=False, context=3)
|
||||
|
||||
def test_get_diff_runs_git_command_with_path_if_its_given(self):
|
||||
comm1 = self.repo[0]
|
||||
comm2 = self.repo[1]
|
||||
self.repo.run_git_command = mock.Mock(return_value=['', ''])
|
||||
self.repo.get_diff(comm1, comm2, 'foo')
|
||||
self.repo.run_git_command.assert_called_once_with(
|
||||
['diff', '-U3', '--full-index', '--binary', '-p', '-M',
|
||||
'--abbrev=40', self.repo._lookup_commit(0),
|
||||
comm2.raw_id, '--', 'foo'])
|
||||
with mock.patch.object(self.repo, '_remote') as remote_mock:
|
||||
self.repo.get_diff(comm1, comm2, 'foo')
|
||||
remote_mock.diff.assert_called_once_with(
|
||||
self.repo._lookup_commit(0), comm2.raw_id,
|
||||
file_filter='foo', opt_ignorews=False, context=3)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vcs_repository_support")
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ def repo(request, baseapp):
|
|||
return repo
|
||||
|
||||
|
||||
class TestMercurialRepository:
|
||||
class TestMercurialRepository(object):
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue