##// END OF EJS Templates
git: replaced some raw subprocess commands with dedicated GIT vcsserver commands.
marcink -
r3862:44edb079 default
parent child Browse files
Show More
@@ -223,17 +223,9 b' class GitCommit(base.BaseCommit):'
223 """
223 """
224 Returns list of child commits.
224 Returns list of child commits.
225 """
225 """
226 rev_filter = settings.GIT_REV_FILTER
227 output, __ = self.repository.run_git_command(
228 ['rev-list', '--children'] + rev_filter)
229
226
230 child_ids = []
227 children = self._remote.children(self.raw_id)
231 pat = re.compile(r'^%s' % self.raw_id)
228 return self._make_commits(children)
232 for l in output.splitlines():
233 if pat.match(l):
234 found_ids = l.split(' ')[1:]
235 child_ids.extend(found_ids)
236 return self._make_commits(child_ids)
237
229
238 def _make_commits(self, commit_ids):
230 def _make_commits(self, commit_ids):
239 def commit_maker(_commit_id):
231 def commit_maker(_commit_id):
@@ -271,52 +263,27 b' class GitCommit(base.BaseCommit):'
271 """
263 """
272 Returns history of file as reversed list of `GitCommit` objects for
264 Returns history of file as reversed list of `GitCommit` objects for
273 which file at given `path` has been modified.
265 which file at given `path` has been modified.
274
275 TODO: This function now uses an underlying 'git' command which works
276 quickly but ideally we should replace with an algorithm.
277 """
266 """
278 self._get_filectx(path)
279 f_path = safe_str(path)
280
267
281 # optimize for n==1, rev-list is much faster for that use-case
268 path = self._get_filectx(path)
282 if limit == 1:
269 hist = self._remote.node_history(self.raw_id, path, limit)
283 cmd = ['rev-list', '-1', self.raw_id, '--', f_path]
284 else:
285 cmd = ['log']
286 if limit:
287 cmd.extend(['-n', str(safe_int(limit, 0))])
288 cmd.extend(['--pretty=format: %H', '-s', self.raw_id, '--', f_path])
289
290 output, __ = self.repository.run_git_command(cmd)
291 commit_ids = re.findall(r'[0-9a-fA-F]{40}', output)
292
293 return [
270 return [
294 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
271 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
295 for commit_id in commit_ids]
272 for commit_id in hist]
296
273
297 def get_file_annotate(self, path, pre_load=None):
274 def get_file_annotate(self, path, pre_load=None):
298 """
275 """
299 Returns a generator of four element tuples with
276 Returns a generator of four element tuples with
300 lineno, commit_id, commit lazy loader and line
277 lineno, commit_id, commit lazy loader and line
278 """
301
279
302 TODO: This function now uses os underlying 'git' command which is
280 result = self._remote.node_annotate(self.raw_id, path)
303 generally not good. Should be replaced with algorithm iterating
304 commits.
305 """
306 cmd = ['blame', '-l', '--root', '-r', self.raw_id, '--', path]
307 # -l ==> outputs long shas (and we need all 40 characters)
308 # --root ==> doesn't put '^' character for bounderies
309 # -r commit_id ==> blames for the given commit
310 output, __ = self.repository.run_git_command(cmd)
311
281
312 for i, blame_line in enumerate(output.split('\n')[:-1]):
282 for ln_no, commit_id, content in result:
313 line_no = i + 1
314 commit_id, line = re.split(r' ', blame_line, 1)
315 yield (
283 yield (
316 line_no, commit_id,
284 ln_no, commit_id,
317 lambda: self.repository.get_commit(commit_id=commit_id,
285 lambda: self.repository.get_commit(commit_id=commit_id, pre_load=pre_load),
318 pre_load=pre_load),
286 content)
319 line)
320
287
321 def get_nodes(self, path):
288 def get_nodes(self, path):
322
289
@@ -549,33 +549,16 b' class GitRepository(BaseRepository):'
549 if path1 is not None and path1 != path:
549 if path1 is not None and path1 != path:
550 raise ValueError("Diff of two different paths not supported.")
550 raise ValueError("Diff of two different paths not supported.")
551
551
552 flags = [
552 if path:
553 '-U%s' % context, '--full-index', '--binary', '-p',
553 file_filter = path
554 '-M', '--abbrev=40']
555 if ignore_whitespace:
556 flags.append('-w')
557
558 if commit1 == self.EMPTY_COMMIT:
559 cmd = ['show'] + flags + [commit2.raw_id]
560 else:
554 else:
561 cmd = ['diff'] + flags + [commit1.raw_id, commit2.raw_id]
555 file_filter = None
562
563 if path:
564 cmd.extend(['--', path])
565
556
566 stdout, __ = self.run_git_command(cmd)
557 diff = self._remote.diff(
567 # If we used 'show' command, strip first few lines (until actual diff
558 commit1.raw_id, commit2.raw_id, file_filter=file_filter,
568 # starts)
559 opt_ignorews=ignore_whitespace,
569 if commit1 == self.EMPTY_COMMIT:
560 context=context)
570 lines = stdout.splitlines()
561 return GitDiff(diff)
571 x = 0
572 for line in lines:
573 if line.startswith('diff'):
574 break
575 x += 1
576 # Append new line just like 'diff' command do
577 stdout = '\n'.join(lines[x:]) + '\n'
578 return GitDiff(stdout)
579
562
580 def strip(self, commit_id, branch_name):
563 def strip(self, commit_id, branch_name):
581 commit = self.get_commit(commit_id=commit_id)
564 commit = self.get_commit(commit_id=commit_id)
@@ -266,8 +266,7 b' class MercurialCommit(base.BaseCommit):'
266 for ln_no, commit_id, content in result:
266 for ln_no, commit_id, content in result:
267 yield (
267 yield (
268 ln_no, commit_id,
268 ln_no, commit_id,
269 lambda: self.repository.get_commit(commit_id=commit_id,
269 lambda: self.repository.get_commit(commit_id=commit_id, pre_load=pre_load),
270 pre_load=pre_load),
271 content)
270 content)
272
271
273 def get_nodes(self, path):
272 def get_nodes(self, path):
@@ -1065,37 +1065,35 b' class TestGitSpecificWithRepo(BackendTes'
1065
1065
1066 def test_paths_fast_traversing(self):
1066 def test_paths_fast_traversing(self):
1067 commit = self.repo.get_commit()
1067 commit = self.repo.get_commit()
1068 assert (
1068 assert commit.get_node('foobar/static/js/admin/base.js').content == 'base'
1069 commit.get_node('foobar/static/js/admin/base.js').content ==
1070 'base')
1071
1069
1072 def test_get_diff_runs_git_command_with_hashes(self):
1070 def test_get_diff_runs_git_command_with_hashes(self):
1073 comm1 = self.repo[0]
1071 comm1 = self.repo[0]
1074 comm2 = self.repo[1]
1072 comm2 = self.repo[1]
1075 self.repo.run_git_command = mock.Mock(return_value=['', ''])
1073
1076 self.repo.get_diff(comm1, comm2)
1074 with mock.patch.object(self.repo, '_remote') as remote_mock:
1075 self.repo.get_diff(comm1, comm2)
1077
1076
1078 self.repo.run_git_command.assert_called_once_with(
1077 remote_mock.diff.assert_called_once_with(
1079 ['diff', '-U3', '--full-index', '--binary', '-p', '-M',
1078 comm1.raw_id, comm2.raw_id,
1080 '--abbrev=40', comm1.raw_id, comm2.raw_id])
1079 file_filter=None, opt_ignorews=False, context=3)
1081
1080
1082 def test_get_diff_runs_git_command_with_str_hashes(self):
1081 def test_get_diff_runs_git_command_with_str_hashes(self):
1083 comm2 = self.repo[1]
1082 comm2 = self.repo[1]
1084 self.repo.run_git_command = mock.Mock(return_value=['', ''])
1083 with mock.patch.object(self.repo, '_remote') as remote_mock:
1085 self.repo.get_diff(self.repo.EMPTY_COMMIT, comm2)
1084 self.repo.get_diff(self.repo.EMPTY_COMMIT, comm2)
1086 self.repo.run_git_command.assert_called_once_with(
1085 remote_mock.diff.assert_called_once_with(
1087 ['show', '-U3', '--full-index', '--binary', '-p', '-M',
1086 self.repo.EMPTY_COMMIT.raw_id, comm2.raw_id,
1088 '--abbrev=40', comm2.raw_id])
1087 file_filter=None, opt_ignorews=False, context=3)
1089
1088
1090 def test_get_diff_runs_git_command_with_path_if_its_given(self):
1089 def test_get_diff_runs_git_command_with_path_if_its_given(self):
1091 comm1 = self.repo[0]
1090 comm1 = self.repo[0]
1092 comm2 = self.repo[1]
1091 comm2 = self.repo[1]
1093 self.repo.run_git_command = mock.Mock(return_value=['', ''])
1092 with mock.patch.object(self.repo, '_remote') as remote_mock:
1094 self.repo.get_diff(comm1, comm2, 'foo')
1093 self.repo.get_diff(comm1, comm2, 'foo')
1095 self.repo.run_git_command.assert_called_once_with(
1094 remote_mock.diff.assert_called_once_with(
1096 ['diff', '-U3', '--full-index', '--binary', '-p', '-M',
1095 self.repo._lookup_commit(0), comm2.raw_id,
1097 '--abbrev=40', self.repo._lookup_commit(0),
1096 file_filter='foo', opt_ignorews=False, context=3)
1098 comm2.raw_id, '--', 'foo'])
1099
1097
1100
1098
1101 @pytest.mark.usefixtures("vcs_repository_support")
1099 @pytest.mark.usefixtures("vcs_repository_support")
@@ -57,7 +57,7 b' def repo(request, baseapp):'
57 return repo
57 return repo
58
58
59
59
60 class TestMercurialRepository:
60 class TestMercurialRepository(object):
61
61
62 # pylint: disable=protected-access
62 # pylint: disable=protected-access
63
63
General Comments 0
You need to be logged in to leave comments. Login now