Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: tests/git_cl_test.py

Issue 1830973003: git cl: Rework Changelist class for Rietveld/Gerrit use. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: review Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« git_cl.py ('K') | « git_cl.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Unit tests for git_cl.py.""" 6 """Unit tests for git_cl.py."""
7 7
8 import os 8 import os
9 import StringIO 9 import StringIO
10 import stat 10 import stat
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 156
157 if find_copies: 157 if find_copies:
158 stat_call = ((['git', 'diff', '--no-ext-diff', '--stat', 158 stat_call = ((['git', 'diff', '--no-ext-diff', '--stat',
159 '--find-copies-harder', '-l100000', '-C'+similarity, 159 '--find-copies-harder', '-l100000', '-C'+similarity,
160 'fake_ancestor_sha', 'HEAD'],), '+dat') 160 'fake_ancestor_sha', 'HEAD'],), '+dat')
161 else: 161 else:
162 stat_call = ((['git', 'diff', '--no-ext-diff', '--stat', 162 stat_call = ((['git', 'diff', '--no-ext-diff', '--stat',
163 '-M'+similarity, 'fake_ancestor_sha', 'HEAD'],), '+dat') 163 '-M'+similarity, 'fake_ancestor_sha', 'HEAD'],), '+dat')
164 164
165 return [ 165 return [
166 ((['git', 'config', 'rietveld.autoupdate'],), ''),
167 ((['git', 'config', 'rietveld.server'],),
168 'codereview.example.com'),
169 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 166 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
170 similarity_call, 167 similarity_call,
171 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 168 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
172 find_copies_call, 169 find_copies_call,
173 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 170 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
171 ((['git', 'config', 'branch.master.rietveldissue'],), ''),
172 ((['git', 'config', 'branch.master.gerritissue'],), ''),
173 ((['git', 'config', 'rietveld.autoupdate'],), ''),
174 ((['git', 'config', 'gerrit.host'],), ''),
175 ((['git', 'config', 'rietveld.server'],),
176 'codereview.example.com'),
174 ((['git', 'config', 'branch.master.merge'],), 'master'), 177 ((['git', 'config', 'branch.master.merge'],), 'master'),
175 ((['git', 'config', 'branch.master.remote'],), 'origin'), 178 ((['git', 'config', 'branch.master.remote'],), 'origin'),
176 ((['get_or_create_merge_base', 'master', 'master'],), 179 ((['get_or_create_merge_base', 'master', 'master'],),
177 'fake_ancestor_sha'), 180 'fake_ancestor_sha'),
178 ((['git', 'config', 'gerrit.host'],), ''),
179 ((['git', 'config', 'branch.master.rietveldissue'],), ''),
180 ] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [ 181 ] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [
181 ((['git', 'rev-parse', '--show-cdup'],), ''), 182 ((['git', 'rev-parse', '--show-cdup'],), ''),
182 ((['git', 'rev-parse', 'HEAD'],), '12345'), 183 ((['git', 'rev-parse', 'HEAD'],), '12345'),
183 ((['git', 'diff', '--name-status', '--no-renames', '-r', 184 ((['git', 'diff', '--name-status', '--no-renames', '-r',
184 'fake_ancestor_sha...', '.'],), 185 'fake_ancestor_sha...', '.'],),
185 'M\t.gitignore\n'), 186 'M\t.gitignore\n'),
186 ((['git', 'config', 'branch.master.rietveldpatchset'],), 187 ((['git', 'config', 'branch.master.rietveldpatchset'],),
187 ''), 188 ''),
188 ((['git', 'log', '--pretty=format:%s%n%n%b', 189 ((['git', 'log', '--pretty=format:%s%n%n%b',
189 'fake_ancestor_sha...'],), 190 'fake_ancestor_sha...'],),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 ((['git', 'config', 'rietveld.autoupdate'],), 273 ((['git', 'config', 'rietveld.autoupdate'],),
273 ''), 274 ''),
274 ((['git', 'config', 'rietveld.pending-ref-prefix'],), 275 ((['git', 'config', 'rietveld.pending-ref-prefix'],),
275 ''), 276 ''),
276 ((['git', 277 ((['git',
277 'config', '--local', '--get-regexp', '^svn-remote\\.'],), 278 'config', '--local', '--get-regexp', '^svn-remote\\.'],),
278 ((('svn-remote.svn.url svn://svn.chromium.org/chrome\n' 279 ((('svn-remote.svn.url svn://svn.chromium.org/chrome\n'
279 'svn-remote.svn.fetch trunk/src:refs/remotes/origin/master'), 280 'svn-remote.svn.fetch trunk/src:refs/remotes/origin/master'),
280 None), 281 None),
281 0)), 282 0)),
282 ((['git',
283 'config', 'rietveld.server'],), 'codereview.example.com'),
284 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), 283 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
285 ((['git', 'config', '--int', '--get', 284 ((['git', 'config', '--int', '--get',
286 'branch.working.git-cl-similarity'],), ''), 285 'branch.working.git-cl-similarity'],), ''),
287 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), 286 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
288 ((['git', 'config', '--int', '--get', 287 ((['git', 'config', '--int', '--get',
289 'branch.working.git-find-copies'],), ''), 288 'branch.working.git-find-copies'],), ''),
290 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), 289 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
291 ((['git', 290 ((['git',
291 'config', 'branch.working.rietveldissue'],), '12345'),
292 ((['git',
293 'config', 'rietveld.server'],), 'codereview.example.com'),
294 ((['git',
292 'config', 'branch.working.merge'],), 'refs/heads/master'), 295 'config', 'branch.working.merge'],), 'refs/heads/master'),
293 ((['git', 'config', 'branch.working.remote'],), 'origin'), 296 ((['git', 'config', 'branch.working.remote'],), 'origin'),
294 ((['git', 'config', 'branch.working.merge'],), 297 ((['git', 'config', 'branch.working.merge'],),
295 'refs/heads/master'), 298 'refs/heads/master'),
296 ((['git', 'config', 'branch.working.remote'],), 'origin'), 299 ((['git', 'config', 'branch.working.remote'],), 'origin'),
297 ((['git', 'rev-list', '--merges', 300 ((['git', 'rev-list', '--merges',
298 '--grep=^SVN changes up to revision [0-9]*$', 301 '--grep=^SVN changes up to revision [0-9]*$',
299 'refs/remotes/origin/master^!'],), ''), 302 'refs/remotes/origin/master^!'],), ''),
300 ((['git', 'rev-list', '^refs/heads/working', 303 ((['git', 'rev-list', '^refs/heads/working',
301 'refs/remotes/origin/master'],), 304 'refs/remotes/origin/master'],),
(...skipping 13 matching lines...) Expand all
315 def _dcommit_calls_normal(cls): 318 def _dcommit_calls_normal(cls):
316 return [ 319 return [
317 ((['git', 'rev-parse', '--show-cdup'],), ''), 320 ((['git', 'rev-parse', '--show-cdup'],), ''),
318 ((['git', 'rev-parse', 'HEAD'],), 321 ((['git', 'rev-parse', 'HEAD'],),
319 '00ff397798ea57439712ed7e04ab96e13969ef40'), 322 '00ff397798ea57439712ed7e04ab96e13969ef40'),
320 ((['git', 323 ((['git',
321 'diff', '--name-status', '--no-renames', '-r', 'fake_ancestor_sha...', 324 'diff', '--name-status', '--no-renames', '-r', 'fake_ancestor_sha...',
322 '.'],), 325 '.'],),
323 'M\tPRESUBMIT.py'), 326 'M\tPRESUBMIT.py'),
324 ((['git', 327 ((['git',
325 'config', 'branch.working.rietveldissue'],), '12345'),
326 ((['git',
327 'config', 'branch.working.rietveldpatchset'],), '31137'), 328 'config', 'branch.working.rietveldpatchset'],), '31137'),
328 ((['git', 'config', 'branch.working.rietveldserver'],), 329 ((['git', 'config', 'branch.working.rietveldserver'],),
329 'codereview.example.com'), 330 'codereview.example.com'),
330 ((['git', 'config', 'user.email'],), 'author@example.com'), 331 ((['git', 'config', 'user.email'],), 'author@example.com'),
331 ((['git', 'config', 'rietveld.tree-status-url'],), ''), 332 ((['git', 'config', 'rietveld.tree-status-url'],), ''),
332 ] 333 ]
333 334
334 @classmethod 335 @classmethod
335 def _dcommit_calls_bypassed(cls): 336 def _dcommit_calls_bypassed(cls):
336 return [ 337 return [
337 ((['git',
338 'config', 'branch.working.rietveldissue'],), '12345'),
339 ((['git', 'config', 'branch.working.rietveldserver'],), 338 ((['git', 'config', 'branch.working.rietveldserver'],),
340 'codereview.example.com'), 339 'codereview.example.com'),
341 ] 340 ]
342 341
343 @classmethod 342 @classmethod
344 def _dcommit_calls_3(cls): 343 def _dcommit_calls_3(cls):
345 return [ 344 return [
346 ((['git', 'config', 'gerrit.host'],), ''),
347 ((['git', 345 ((['git',
348 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', 346 'diff', '--no-ext-diff', '--stat', '--find-copies-harder',
349 '-l100000', '-C50', 'fake_ancestor_sha', 347 '-l100000', '-C50', 'fake_ancestor_sha',
350 'refs/heads/working'],), 348 'refs/heads/working'],),
351 (' PRESUBMIT.py | 2 +-\n' 349 (' PRESUBMIT.py | 2 +-\n'
352 ' 1 files changed, 1 insertions(+), 1 deletions(-)\n')), 350 ' 1 files changed, 1 insertions(+), 1 deletions(-)\n')),
353 ((['git', 'show-ref', '--quiet', '--verify', 351 ((['git', 'show-ref', '--quiet', '--verify',
354 'refs/heads/git-cl-commit'],), 352 'refs/heads/git-cl-commit'],),
355 (('', None), 0)), 353 (('', None), 0)),
356 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), 354 ((['git', 'branch', '-D', 'git-cl-commit'],), ''),
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 self.calls = ( 537 self.calls = (
540 self._dcommit_calls_1() + 538 self._dcommit_calls_1() +
541 self._dcommit_calls_bypassed() + 539 self._dcommit_calls_bypassed() +
542 self._dcommit_calls_3()) 540 self._dcommit_calls_3())
543 git_cl.main(['dcommit', '--bypass-hooks']) 541 git_cl.main(['dcommit', '--bypass-hooks'])
544 542
545 543
546 @classmethod 544 @classmethod
547 def _gerrit_base_calls(cls): 545 def _gerrit_base_calls(cls):
548 return [ 546 return [
549 ((['git', 'config', 'rietveld.autoupdate'],),
550 ''),
551 ((['git',
552 'config', 'rietveld.server'],), 'codereview.example.com'),
553 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 547 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
554 ((['git', 'config', '--int', '--get', 548 ((['git', 'config', '--int', '--get',
555 'branch.master.git-cl-similarity'],), ''), 549 'branch.master.git-cl-similarity'],), ''),
556 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 550 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
557 ((['git', 'config', '--int', '--get', 551 ((['git', 'config', '--int', '--get',
558 'branch.master.git-find-copies'],), ''), 552 'branch.master.git-find-copies'],), ''),
559 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), 553 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
554 ((['git', 'config', 'branch.master.rietveldissue'],), ''),
555 ((['git', 'config', 'branch.master.gerritissue'],), ''),
556 ((['git', 'config', 'rietveld.autoupdate'],), ''),
557 ((['git', 'config', 'gerrit.host'],), 'True'),
560 ((['git', 'config', 'branch.master.merge'],), 'master'), 558 ((['git', 'config', 'branch.master.merge'],), 'master'),
561 ((['git', 'config', 'branch.master.remote'],), 'origin'), 559 ((['git', 'config', 'branch.master.remote'],), 'origin'),
562 ((['get_or_create_merge_base', 'master', 'master'],), 560 ((['get_or_create_merge_base', 'master', 'master'],),
563 'fake_ancestor_sha'), 561 'fake_ancestor_sha'),
564 ((['git', 'config', 'gerrit.host'],), 'True'), 562 ] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [
565 ] + cls._git_sanity_checks('fake_ancestor_sha', 'master') + [
566 ((['git', 'rev-parse', '--show-cdup'],), ''), 563 ((['git', 'rev-parse', '--show-cdup'],), ''),
567 ((['git', 'rev-parse', 'HEAD'],), '12345'), 564 ((['git', 'rev-parse', 'HEAD'],), '12345'),
568 ((['git', 565 ((['git',
569 'diff', '--name-status', '--no-renames', '-r', 566 'diff', '--name-status', '--no-renames', '-r',
570 'fake_ancestor_sha...', '.'],), 567 'fake_ancestor_sha...', '.'],),
571 'M\t.gitignore\n'), 568 'M\t.gitignore\n'),
572 ((['git', 'config', 'branch.master.rietveldissue'],), ''), 569 ((['git', 'config', 'branch.master.gerritpatchset'],), ''),
573 ((['git',
574 'config', 'branch.master.rietveldpatchset'],), ''),
575 ((['git', 570 ((['git',
576 'log', '--pretty=format:%s%n%n%b', 'fake_ancestor_sha...'],), 571 'log', '--pretty=format:%s%n%n%b', 'fake_ancestor_sha...'],),
577 'foo'), 572 'foo'),
578 ((['git', 'config', 'user.email'],), 'me@example.com'), 573 ((['git', 'config', 'user.email'],), 'me@example.com'),
579 ((['git', 574 ((['git',
580 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', 575 'diff', '--no-ext-diff', '--stat', '--find-copies-harder',
581 '-l100000', '-C50', 'fake_ancestor_sha', 'HEAD'],), 576 '-l100000', '-C50', 'fake_ancestor_sha', 'HEAD'],),
582 '+dat'), 577 '+dat'),
583 ] 578 ]
584 579
585 @classmethod 580 @classmethod
586 def _gerrit_upload_calls(cls, description, reviewers, squash, 581 def _gerrit_upload_calls(cls, description, reviewers, squash,
587 expected_upstream_ref='origin/refs/heads/master', 582 expected_upstream_ref='origin/refs/heads/master',
588 post_amend_description=None): 583 post_amend_description=None):
589 if post_amend_description is None: 584 if post_amend_description is None:
590 post_amend_description = description 585 post_amend_description = description
591 calls = [ 586 calls = [
592 ((['git', 'config', '--bool', 'gerrit.squash-uploads'],), 'false'), 587 ((['git', 'config', '--bool', 'gerrit.squash-uploads'],), 'false'),
593 ((['git', 'log', '--pretty=format:%s\n\n%b', 588 ((['git', 'log', '--pretty=format:%s\n\n%b',
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 'remote: Processing changes: new: 1, done\n' 650 'remote: Processing changes: new: 1, done\n'
656 'remote:\n' 651 'remote:\n'
657 'remote: New Changes:\n' 652 'remote: New Changes:\n'
658 'remote: https://chromium-review.googlesource.com/123456 XXX.\n' 653 'remote: https://chromium-review.googlesource.com/123456 XXX.\n'
659 'remote:\n' 654 'remote:\n'
660 'To https://chromium.googlesource.com/yyy/zzz\n' 655 'To https://chromium.googlesource.com/yyy/zzz\n'
661 ' * [new branch] hhhh -> refs/for/refs/heads/master\n')), 656 ' * [new branch] hhhh -> refs/for/refs/heads/master\n')),
662 ] 657 ]
663 if squash: 658 if squash:
664 calls += [ 659 calls += [
665 ((['git', 'config', 'branch.master.rietveldissue', '123456'],), ''), 660 ((['git', 'config', 'branch.master.gerritissue', '123456'],), ''),
661 ((['git', 'config', 'branch.master.gerritserver'],), ''),
662 ((['git', 'config', 'remote.origin.url'],),
663 'https://chromium.googlesource.com/my/repo.git'),
664 ((['git', 'config', 'branch.master.gerritserver',
665 'https://chromium-review.googlesource.com'],), ''),
666 ((['git', 'rev-parse', 'HEAD'],), 'abcdef0123456789'), 666 ((['git', 'rev-parse', 'HEAD'],), 'abcdef0123456789'),
667 ((['git', 'update-ref', '-m', 'Uploaded abcdef0123456789', 667 ((['git', 'update-ref', '-m', 'Uploaded abcdef0123456789',
668 'refs/heads/git_cl_uploads/master', 'abcdef0123456789'],), 668 'refs/heads/git_cl_uploads/master', 'abcdef0123456789'],),
669 '') 669 '')
670 ] 670 ]
671 calls += cls._git_post_upload_calls() 671 calls += cls._git_post_upload_calls()
672 return calls 672 return calls
673 673
674 def _run_gerrit_upload_test( 674 def _run_gerrit_upload_test(
675 self, 675 self,
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 # Patch when local tree is dirty 879 # Patch when local tree is dirty
880 self.mock(git_common, 'is_dirty_git_tree', lambda x: True) 880 self.mock(git_common, 'is_dirty_git_tree', lambda x: True)
881 self.assertNotEqual(git_cl.main(['patch', '123456']), 0) 881 self.assertNotEqual(git_cl.main(['patch', '123456']), 0)
882 882
883 def test_diff_when_dirty(self): 883 def test_diff_when_dirty(self):
884 # Do 'git cl diff' when local tree is dirty 884 # Do 'git cl diff' when local tree is dirty
885 self.mock(git_common, 'is_dirty_git_tree', lambda x: True) 885 self.mock(git_common, 'is_dirty_git_tree', lambda x: True)
886 self.assertNotEqual(git_cl.main(['diff']), 0) 886 self.assertNotEqual(git_cl.main(['diff']), 0)
887 887
888 def _patch_common(self): 888 def _patch_common(self):
889 self.mock(git_cl.Changelist, 'GetMostRecentPatchset', lambda x: '60001') 889 self.mock(git_cl._RietveldChangelistImpl, 'GetMostRecentPatchset',
890 self.mock(git_cl.Changelist, 'GetPatchSetDiff', lambda *args: None) 890 lambda x: '60001')
891 self.mock(git_cl.Changelist, 'GetDescription', lambda *args: 'Description') 891 self.mock(git_cl._RietveldChangelistImpl, 'GetPatchSetDiff',
892 lambda *args: None)
893 self.mock(git_cl.Changelist, 'GetDescription',
894 lambda *args: 'Description')
892 self.mock(git_cl.Changelist, 'SetIssue', lambda *args: None) 895 self.mock(git_cl.Changelist, 'SetIssue', lambda *args: None)
893 self.mock(git_cl.Changelist, 'SetPatchset', lambda *args: None) 896 self.mock(git_cl.Changelist, 'SetPatchset', lambda *args: None)
894 self.mock(git_cl, 'IsGitVersionAtLeast', lambda *args: True) 897 self.mock(git_cl, 'IsGitVersionAtLeast', lambda *args: True)
895 898
896 self.calls = [ 899 self.calls = [
897 ((['git', 'config', 'rietveld.autoupdate'],), ''), 900 ((['git', 'config', 'rietveld.autoupdate'],), ''),
898 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), 901 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'),
899 ((['git', 'rev-parse', '--show-cdup'],), ''), 902 ((['git', 'rev-parse', '--show-cdup'],), ''),
900 ((['sed', '-e', 's|^--- a/|--- |; s|^+++ b/|+++ |'],), ''), 903 ((['sed', '-e', 's|^--- a/|--- |; s|^+++ b/|+++ |'],), ''),
901 ] 904 ]
902 905
903 def test_patch_successful(self): 906 def test_patch_successful(self):
904 self._patch_common() 907 self._patch_common()
905 self.calls += [ 908 self.calls += [
906 ((['git', 'apply', '--index', '-p0', '--3way'],), ''), 909 ((['git', 'apply', '--index', '-p0', '--3way'],), ''),
907 ((['git', 'commit', '-m', 910 ((['git', 'commit', '-m',
908 'Description\n\n' + 911 'Description\n\n' +
909 'patch from issue 123456 at patchset 60001 ' + 912 'patch from issue 123456 at patchset 60001 ' +
910 '(http://crrev.com/123456#ps60001)'],), ''), 913 '(http://crrev.com/123456#ps60001)'],), ''),
914 ((['git', 'symbolic-ref', 'HEAD'],), 'master'),
915 ((['git', 'config', 'branch.master.rietveldserver'],), ''),
911 ] 916 ]
912 self.assertEqual(git_cl.main(['patch', '123456']), 0) 917 self.assertEqual(git_cl.main(['patch', '123456']), 0)
913 918
914 def test_patch_conflict(self): 919 def test_patch_conflict(self):
915 self._patch_common() 920 self._patch_common()
916 self.calls += [ 921 self.calls += [
917 ((['git', 'apply', '--index', '-p0', '--3way'],), '', 922 ((['git', 'apply', '--index', '-p0', '--3way'],), '',
918 subprocess2.CalledProcessError(1, '', '', '', '')), 923 subprocess2.CalledProcessError(1, '', '', '', '')),
919 ] 924 ]
920 self.assertNotEqual(git_cl.main(['patch', '123456']), 0) 925 self.assertNotEqual(git_cl.main(['patch', '123456']), 0)
921 926
922 if __name__ == '__main__': 927 if __name__ == '__main__':
923 git_cl.logging.basicConfig( 928 git_cl.logging.basicConfig(
924 level=git_cl.logging.DEBUG if '-v' in sys.argv else git_cl.logging.ERROR) 929 level=git_cl.logging.DEBUG if '-v' in sys.argv else git_cl.logging.ERROR)
925 unittest.main() 930 unittest.main()
OLDNEW
« git_cl.py ('K') | « git_cl.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698