Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 7 | 7 |
| 8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
| 9 | 9 |
| 10 import json | 10 import json |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 return fn | 83 return fn |
| 84 return hook | 84 return hook |
| 85 | 85 |
| 86 | 86 |
| 87 def ask_for_data(prompt): | 87 def ask_for_data(prompt): |
| 88 try: | 88 try: |
| 89 return raw_input(prompt) | 89 return raw_input(prompt) |
| 90 except KeyboardInterrupt: | 90 except KeyboardInterrupt: |
| 91 # Hide the exception. | 91 # Hide the exception. |
| 92 sys.exit(1) | 92 sys.exit(1) |
| 93 | 93 |
|
M-A Ruel
2012/10/16 22:38:09
2 lines between file-level symbols
| |
| 94 def git_set_branch_value(key, value): | |
| 95 branch = Changelist().GetBranch() | |
| 96 if branch: | |
| 97 git_key = 'branch.%s.%s' % (branch, key) | |
| 98 RunGit(['config', '--int', git_key, str(value)]) | |
| 99 | |
| 100 def git_get_branch_default(key, default): | |
| 101 branch = Changelist().GetBranch() | |
| 102 if branch: | |
| 103 git_key = 'branch.%s.%s' % (branch, key) | |
| 104 (_, stdout) = RunGitWithCode(['config', '--int', '--get', git_key]) | |
| 105 try: | |
| 106 return int(stdout.strip()) | |
| 107 except ValueError: | |
| 108 pass | |
| 109 return default | |
| 94 | 110 |
| 95 def add_git_similarity(parser): | 111 def add_git_similarity(parser): |
| 96 parser.add_option( | 112 parser.add_option( |
| 97 '--similarity', metavar='SIM', type='int', action='store', default=None, | 113 '--similarity', metavar='SIM', type='int', action='store', default=None, |
| 98 help='Sets the percentage that a pair of files need to match in order to' | 114 help='Sets the percentage that a pair of files need to match in order to' |
| 99 ' be considered copies (default 50)') | 115 ' be considered copies (default 50)') |
| 116 parser.add_option( | |
| 117 '--find-copies', action='store_true', default=None, | |
|
M-A Ruel
2012/10/16 22:38:09
default=None is redundant with default's default v
| |
| 118 help='Allows git to look for copies.') | |
| 119 parser.add_option( | |
| 120 '--no-find-copies', action='store_false', dest='find_copies', | |
|
M-A Ruel
2012/10/16 22:38:09
git-cl doesn't have --foo --no-foo arguments. Just
iannucci
2012/10/16 22:57:14
The reason I did this is so that you can un-set it
M-A Ruel
2012/10/16 23:31:27
Ok, sorry I missed it.
| |
| 121 help='Disallows git from looking for copies.') | |
| 100 | 122 |
| 101 old_parser_args = parser.parse_args | 123 old_parser_args = parser.parse_args |
| 102 def Parse(args): | 124 def Parse(args): |
| 103 options, args = old_parser_args(args) | 125 options, args = old_parser_args(args) |
| 104 | 126 |
| 105 branch = Changelist().GetBranch() | |
| 106 key = 'branch.%s.git-cl-similarity' % branch | |
| 107 if options.similarity is None: | 127 if options.similarity is None: |
| 108 if branch: | 128 options.similarity = git_get_branch_default('git-cl-similarity', 50) |
| 109 (_, stdout) = RunGitWithCode(['config', '--int', '--get', key]) | |
| 110 try: | |
| 111 options.similarity = int(stdout.strip()) | |
| 112 except ValueError: | |
| 113 pass | |
| 114 options.similarity = options.similarity or 50 | |
| 115 else: | 129 else: |
| 116 if branch: | 130 print('Note: Saving similarity of %d%% in git config.' |
| 117 print('Note: Saving similarity of %d%% in git config.' | 131 % options.similarity) |
| 118 % options.similarity) | 132 git_set_branch_value('git-cl-similarity', str(options.similarity)) |
| 119 RunGit(['config', '--int', key, str(options.similarity)]) | |
| 120 | 133 |
| 121 options.similarity = max(1, min(options.similarity, 100)) | 134 options.similarity = max(0, min(options.similarity, 100)) |
| 135 | |
| 136 if options.find_copies is None: | |
| 137 options.find_copies = bool( | |
| 138 git_get_branch_default('git-find-copies', True)) | |
| 139 else: | |
| 140 git_set_branch_value('git-find-copies', int(options.find_copies)) | |
| 122 | 141 |
| 123 print('Using %d%% similarity for rename/copy detection. ' | 142 print('Using %d%% similarity for rename/copy detection. ' |
| 124 'Override with --similarity.' % options.similarity) | 143 'Override with --similarity.' % options.similarity) |
| 125 | 144 |
| 126 return options, args | 145 return options, args |
| 127 parser.parse_args = Parse | 146 parser.parse_args = Parse |
| 128 | 147 |
| 129 | 148 |
| 130 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): | 149 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): |
| 131 """Return the corresponding git ref if |base_url| together with |glob_spec| | 150 """Return the corresponding git ref if |base_url| together with |glob_spec| |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 162 # Parse specs like "trunk/src:refs/remotes/origin/trunk". | 181 # Parse specs like "trunk/src:refs/remotes/origin/trunk". |
| 163 if fetch_suburl: | 182 if fetch_suburl: |
| 164 full_url = base_url + '/' + fetch_suburl | 183 full_url = base_url + '/' + fetch_suburl |
| 165 else: | 184 else: |
| 166 full_url = base_url | 185 full_url = base_url |
| 167 if full_url == url: | 186 if full_url == url: |
| 168 return as_ref | 187 return as_ref |
| 169 return None | 188 return None |
| 170 | 189 |
| 171 | 190 |
| 172 def print_stats(similarity, args): | 191 def print_stats(similarity, find_copies, args): |
| 173 """Prints statistics about the change to the user.""" | 192 """Prints statistics about the change to the user.""" |
| 174 # --no-ext-diff is broken in some versions of Git, so try to work around | 193 # --no-ext-diff is broken in some versions of Git, so try to work around |
| 175 # this by overriding the environment (but there is still a problem if the | 194 # this by overriding the environment (but there is still a problem if the |
| 176 # git config key "diff.external" is used). | 195 # git config key "diff.external" is used). |
| 177 env = os.environ.copy() | 196 env = os.environ.copy() |
| 178 if 'GIT_EXTERNAL_DIFF' in env: | 197 if 'GIT_EXTERNAL_DIFF' in env: |
| 179 del env['GIT_EXTERNAL_DIFF'] | 198 del env['GIT_EXTERNAL_DIFF'] |
| 199 | |
| 200 if find_copies: | |
| 201 similarity_options = ['--find-copies-harder', '-l100000', | |
| 202 '-C%s' % similarity] | |
| 203 else: | |
| 204 similarity_options = ['-M', '-M'] | |
|
M-A Ruel
2012/10/16 22:38:09
'-M%d' % similarity.
iannucci
2012/10/16 22:57:14
Of course I miss out on the entire point of doing
M-A Ruel
2012/10/16 23:31:27
Errr, there's not really a point in specifying -M
| |
| 205 | |
| 180 return subprocess2.call( | 206 return subprocess2.call( |
| 181 ['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', | 207 ['git', 'diff', '--no-ext-diff', '--stat'] + similarity_options + args, |
| 182 '-C%s' % similarity, '-l100000'] + args, env=env) | 208 env=env) |
| 183 | 209 |
| 184 | 210 |
| 185 class Settings(object): | 211 class Settings(object): |
| 186 def __init__(self): | 212 def __init__(self): |
| 187 self.default_server = None | 213 self.default_server = None |
| 188 self.cc = None | 214 self.cc = None |
| 189 self.root = None | 215 self.root = None |
| 190 self.is_git_svn = None | 216 self.is_git_svn = None |
| 191 self.svn_branch = None | 217 self.svn_branch = None |
| 192 self.tree_status_url = None | 218 self.tree_status_url = None |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1066 upload_args.extend(['--reviewers', change_desc.reviewers]) | 1092 upload_args.extend(['--reviewers', change_desc.reviewers]) |
| 1067 if options.send_mail: | 1093 if options.send_mail: |
| 1068 if not change_desc.reviewers: | 1094 if not change_desc.reviewers: |
| 1069 DieWithError("Must specify reviewers to send email.") | 1095 DieWithError("Must specify reviewers to send email.") |
| 1070 upload_args.append('--send_mail') | 1096 upload_args.append('--send_mail') |
| 1071 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) | 1097 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) |
| 1072 if cc: | 1098 if cc: |
| 1073 upload_args.extend(['--cc', cc]) | 1099 upload_args.extend(['--cc', cc]) |
| 1074 | 1100 |
| 1075 upload_args.extend(['--git_similarity', str(options.similarity)]) | 1101 upload_args.extend(['--git_similarity', str(options.similarity)]) |
| 1102 if options.find_copies: | |
| 1103 upload_args.extend(['--git_find_copies']) | |
| 1104 else: | |
| 1105 upload_args.extend(['--git_no_find_copies']) | |
| 1076 | 1106 |
| 1077 # Include the upstream repo's URL in the change -- this is useful for | 1107 # Include the upstream repo's URL in the change -- this is useful for |
| 1078 # projects that have their source spread across multiple repos. | 1108 # projects that have their source spread across multiple repos. |
| 1079 remote_url = cl.GetGitBaseUrlFromConfig() | 1109 remote_url = cl.GetGitBaseUrlFromConfig() |
| 1080 if not remote_url: | 1110 if not remote_url: |
| 1081 if settings.GetIsGitSvn(): | 1111 if settings.GetIsGitSvn(): |
| 1082 # URL is dependent on the current directory. | 1112 # URL is dependent on the current directory. |
| 1083 data = RunGit(['svn', 'info'], cwd=settings.GetRoot()) | 1113 data = RunGit(['svn', 'info'], cwd=settings.GetRoot()) |
| 1084 if data: | 1114 if data: |
| 1085 keys = dict(line.split(': ', 1) for line in data.splitlines() | 1115 keys = dict(line.split(': ', 1) for line in data.splitlines() |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1169 if not options.bypass_hooks: | 1199 if not options.bypass_hooks: |
| 1170 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, | 1200 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
| 1171 may_prompt=not options.force, | 1201 may_prompt=not options.force, |
| 1172 verbose=options.verbose, | 1202 verbose=options.verbose, |
| 1173 author=None) | 1203 author=None) |
| 1174 if not hook_results.should_continue(): | 1204 if not hook_results.should_continue(): |
| 1175 return 1 | 1205 return 1 |
| 1176 if not options.reviewers and hook_results.reviewers: | 1206 if not options.reviewers and hook_results.reviewers: |
| 1177 options.reviewers = hook_results.reviewers | 1207 options.reviewers = hook_results.reviewers |
| 1178 | 1208 |
| 1179 print_stats(options.similarity, args) | 1209 print_stats(options.similarity, options.find_copies, args) |
| 1180 if settings.GetIsGerrit(): | 1210 if settings.GetIsGerrit(): |
| 1181 return GerritUpload(options, args, cl) | 1211 return GerritUpload(options, args, cl) |
| 1182 return RietveldUpload(options, args, cl) | 1212 return RietveldUpload(options, args, cl) |
| 1183 | 1213 |
| 1184 | 1214 |
| 1185 def IsSubmoduleMergeCommit(ref): | 1215 def IsSubmoduleMergeCommit(ref): |
| 1186 # When submodules are added to the repo, we expect there to be a single | 1216 # When submodules are added to the repo, we expect there to be a single |
| 1187 # non-git-svn merge commit at remote HEAD with a signature comment. | 1217 # non-git-svn merge commit at remote HEAD with a signature comment. |
| 1188 pattern = '^SVN changes up to revision [0-9]*$' | 1218 pattern = '^SVN changes up to revision [0-9]*$' |
| 1189 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] | 1219 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1303 | 1333 |
| 1304 if cl.GetIssue(): | 1334 if cl.GetIssue(): |
| 1305 description += "\n\nReview URL: %s" % cl.GetIssueURL() | 1335 description += "\n\nReview URL: %s" % cl.GetIssueURL() |
| 1306 | 1336 |
| 1307 if options.contributor: | 1337 if options.contributor: |
| 1308 description += "\nPatch from %s." % options.contributor | 1338 description += "\nPatch from %s." % options.contributor |
| 1309 print 'Description:', repr(description) | 1339 print 'Description:', repr(description) |
| 1310 | 1340 |
| 1311 branches = [base_branch, cl.GetBranchRef()] | 1341 branches = [base_branch, cl.GetBranchRef()] |
| 1312 if not options.force: | 1342 if not options.force: |
| 1313 print_stats(options.similarity, branches) | 1343 print_stats(options.similarity, options.find_copies, branches) |
| 1314 ask_for_data('About to commit; enter to confirm.') | 1344 ask_for_data('About to commit; enter to confirm.') |
| 1315 | 1345 |
| 1316 # We want to squash all this branch's commits into one commit with the proper | 1346 # We want to squash all this branch's commits into one commit with the proper |
| 1317 # description. We do this by doing a "reset --soft" to the base branch (which | 1347 # description. We do this by doing a "reset --soft" to the base branch (which |
| 1318 # keeps the working copy the same), then dcommitting that. If origin/master | 1348 # keeps the working copy the same), then dcommitting that. If origin/master |
| 1319 # has a submodule merge commit, we'll also need to cherry-pick the squashed | 1349 # has a submodule merge commit, we'll also need to cherry-pick the squashed |
| 1320 # commit onto a branch based on the git-svn head. | 1350 # commit onto a branch based on the git-svn head. |
| 1321 MERGE_BRANCH = 'git-cl-commit' | 1351 MERGE_BRANCH = 'git-cl-commit' |
| 1322 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' | 1352 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' |
| 1323 # Delete the branches if they exist. | 1353 # Delete the branches if they exist. |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1758 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1788 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1759 | 1789 |
| 1760 # Not a known command. Default to help. | 1790 # Not a known command. Default to help. |
| 1761 GenUsage(parser, 'help') | 1791 GenUsage(parser, 'help') |
| 1762 return CMDhelp(parser, argv) | 1792 return CMDhelp(parser, argv) |
| 1763 | 1793 |
| 1764 | 1794 |
| 1765 if __name__ == '__main__': | 1795 if __name__ == '__main__': |
| 1766 fix_encoding.fix_encoding() | 1796 fix_encoding.fix_encoding() |
| 1767 sys.exit(main(sys.argv[1:])) | 1797 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |