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 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1099 # It is probably not worthwhile to support different workflows. | 1099 # It is probably not worthwhile to support different workflows. |
1100 remote = 'origin' | 1100 remote = 'origin' |
1101 branch = 'master' | 1101 branch = 'master' |
1102 if options.target_branch: | 1102 if options.target_branch: |
1103 branch = options.target_branch | 1103 branch = options.target_branch |
1104 | 1104 |
1105 log_desc = options.message or CreateDescriptionFromLog(args) | 1105 log_desc = options.message or CreateDescriptionFromLog(args) |
1106 if CHANGE_ID not in log_desc: | 1106 if CHANGE_ID not in log_desc: |
1107 AddChangeIdToCommitMessage(options, args) | 1107 AddChangeIdToCommitMessage(options, args) |
1108 if options.reviewers: | 1108 if options.reviewers: |
1109 log_desc += '\nR=' + options.reviewers | 1109 log_desc += '\nR=' + ','.join(options.reviewers) |
1110 change_desc = ChangeDescription(log_desc, options.reviewers) | 1110 change_desc = ChangeDescription(log_desc, ','.join(options.reviewers)) |
Dirk Pranke
2013/04/10 19:55:46
Nit: ', ' (with a space) might be more readable?
M-A Ruel
2013/04/10 20:32:07
Done but it had implications, ptal.
| |
1111 change_desc.ParseDescription() | 1111 change_desc.ParseDescription() |
1112 if change_desc.IsEmpty(): | 1112 if change_desc.IsEmpty(): |
1113 print "Description is empty; aborting." | 1113 print "Description is empty; aborting." |
1114 return 1 | 1114 return 1 |
1115 | 1115 |
1116 receive_options = [] | 1116 receive_options = [] |
1117 cc = cl.GetCCList().split(',') | 1117 cc = cl.GetCCList().split(',') |
1118 if options.cc: | 1118 if options.cc: |
1119 cc += options.cc.split(',') | 1119 cc.extend(options.cc) |
1120 cc = filter(None, cc) | 1120 cc = filter(None, cc) |
1121 if cc: | 1121 if cc: |
1122 receive_options += ['--cc=' + email for email in cc] | 1122 receive_options += ['--cc=' + email for email in cc] |
1123 if change_desc.reviewers: | 1123 if change_desc.reviewers: |
1124 reviewers = filter(None, change_desc.reviewers.split(',')) | 1124 reviewers = filter(None, change_desc.reviewers.split(',')) |
1125 if reviewers: | 1125 if reviewers: |
1126 receive_options += ['--reviewer=' + email for email in reviewers] | 1126 receive_options += ['--reviewer=' + email for email in reviewers] |
1127 | 1127 |
1128 git_command = ['push'] | 1128 git_command = ['push'] |
1129 if receive_options: | 1129 if receive_options: |
(...skipping 22 matching lines...) Expand all Loading... | |
1152 # for upload.py. Soon this will be changed to set the --message option. | 1152 # for upload.py. Soon this will be changed to set the --message option. |
1153 # Will wait until people are used to typing -t instead of -m. | 1153 # Will wait until people are used to typing -t instead of -m. |
1154 upload_args.extend(['--title', options.message]) | 1154 upload_args.extend(['--title', options.message]) |
1155 upload_args.extend(['--issue', str(cl.GetIssue())]) | 1155 upload_args.extend(['--issue', str(cl.GetIssue())]) |
1156 print ("This branch is associated with issue %s. " | 1156 print ("This branch is associated with issue %s. " |
1157 "Adding patch to that issue." % cl.GetIssue()) | 1157 "Adding patch to that issue." % cl.GetIssue()) |
1158 else: | 1158 else: |
1159 if options.title: | 1159 if options.title: |
1160 upload_args.extend(['--title', options.title]) | 1160 upload_args.extend(['--title', options.title]) |
1161 message = options.title or options.message or CreateDescriptionFromLog(args) | 1161 message = options.title or options.message or CreateDescriptionFromLog(args) |
1162 change_desc = ChangeDescription(message, options.reviewers) | 1162 change_desc = ChangeDescription(message, ','.join(options.reviewers)) |
1163 if not options.force: | 1163 if not options.force: |
1164 change_desc.Prompt() | 1164 change_desc.Prompt() |
1165 change_desc.ParseDescription() | 1165 change_desc.ParseDescription() |
1166 | 1166 |
1167 if change_desc.IsEmpty(): | 1167 if change_desc.IsEmpty(): |
1168 print "Description is empty; aborting." | 1168 print "Description is empty; aborting." |
1169 return 1 | 1169 return 1 |
1170 | 1170 |
1171 upload_args.extend(['--message', change_desc.description]) | 1171 upload_args.extend(['--message', change_desc.description]) |
1172 if change_desc.reviewers: | 1172 if change_desc.reviewers: |
1173 upload_args.extend(['--reviewers', change_desc.reviewers]) | 1173 upload_args.extend(['--reviewers', change_desc.reviewers]) |
1174 if options.send_mail: | 1174 if options.send_mail: |
1175 if not change_desc.reviewers: | 1175 if not change_desc.reviewers: |
1176 DieWithError("Must specify reviewers to send email.") | 1176 DieWithError("Must specify reviewers to send email.") |
1177 upload_args.append('--send_mail') | 1177 upload_args.append('--send_mail') |
1178 cc = ','.join(filter(None, (cl.GetCCList(), options.cc))) | 1178 cc = ','.join(filter(None, (cl.GetCCList(), ','.join(options.cc)))) |
1179 if cc: | 1179 if cc: |
1180 upload_args.extend(['--cc', cc]) | 1180 upload_args.extend(['--cc', cc]) |
1181 | 1181 |
1182 upload_args.extend(['--git_similarity', str(options.similarity)]) | 1182 upload_args.extend(['--git_similarity', str(options.similarity)]) |
1183 if not options.find_copies: | 1183 if not options.find_copies: |
1184 upload_args.extend(['--git_no_find_copies']) | 1184 upload_args.extend(['--git_no_find_copies']) |
1185 | 1185 |
1186 # Include the upstream repo's URL in the change -- this is useful for | 1186 # Include the upstream repo's URL in the change -- this is useful for |
1187 # projects that have their source spread across multiple repos. | 1187 # projects that have their source spread across multiple repos. |
1188 remote_url = cl.GetGitBaseUrlFromConfig() | 1188 remote_url = cl.GetGitBaseUrlFromConfig() |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1221 | 1221 |
1222 if not cl.GetIssue(): | 1222 if not cl.GetIssue(): |
1223 cl.SetIssue(issue) | 1223 cl.SetIssue(issue) |
1224 cl.SetPatchset(patchset) | 1224 cl.SetPatchset(patchset) |
1225 | 1225 |
1226 if options.use_commit_queue: | 1226 if options.use_commit_queue: |
1227 cl.SetFlag('commit', '1') | 1227 cl.SetFlag('commit', '1') |
1228 return 0 | 1228 return 0 |
1229 | 1229 |
1230 | 1230 |
1231 def cleanup_list(l): | |
1232 """Fixes a list so that comma separated items are put as individual items. | |
1233 | |
1234 So that "--reviewers joe@c,john@c --reviewers joa@c" results in | |
1235 options.reviewers == sorted(['joe@c', 'john@c', 'joa@c']). | |
1236 """ | |
1237 return sorted(filter(None, sum((i.split(',') for i in l), []))) | |
1238 | |
1239 | |
1231 @usage('[args to "git diff"]') | 1240 @usage('[args to "git diff"]') |
1232 def CMDupload(parser, args): | 1241 def CMDupload(parser, args): |
1233 """upload the current changelist to codereview""" | 1242 """upload the current changelist to codereview""" |
1234 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 1243 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
1235 help='bypass upload presubmit hook') | 1244 help='bypass upload presubmit hook') |
1236 parser.add_option('-f', action='store_true', dest='force', | 1245 parser.add_option('-f', action='store_true', dest='force', |
1237 help="force yes to questions (don't prompt)") | 1246 help="force yes to questions (don't prompt)") |
1238 parser.add_option('-m', dest='message', help='message for patchset') | 1247 parser.add_option('-m', dest='message', help='message for patchset') |
1239 parser.add_option('-t', dest='title', help='title for patchset') | 1248 parser.add_option('-t', dest='title', help='title for patchset') |
1240 parser.add_option('-r', '--reviewers', | 1249 parser.add_option('-r', '--reviewers', |
1250 action='append', default=[], | |
1241 help='reviewer email addresses') | 1251 help='reviewer email addresses') |
1242 parser.add_option('--cc', | 1252 parser.add_option('--cc', |
1253 action='append', default=[], | |
1243 help='cc email addresses') | 1254 help='cc email addresses') |
1244 parser.add_option('-s', '--send-mail', action='store_true', | 1255 parser.add_option('-s', '--send-mail', action='store_true', |
1245 help='send email to reviewer immediately') | 1256 help='send email to reviewer immediately') |
1246 parser.add_option("--emulate_svn_auto_props", action="store_true", | 1257 parser.add_option("--emulate_svn_auto_props", action="store_true", |
1247 dest="emulate_svn_auto_props", | 1258 dest="emulate_svn_auto_props", |
1248 help="Emulate Subversion's auto properties feature.") | 1259 help="Emulate Subversion's auto properties feature.") |
1249 parser.add_option('-c', '--use-commit-queue', action='store_true', | 1260 parser.add_option('-c', '--use-commit-queue', action='store_true', |
1250 help='tell the commit queue to commit this patchset') | 1261 help='tell the commit queue to commit this patchset') |
1251 parser.add_option('--target_branch', | 1262 parser.add_option('--target_branch', |
1252 help='When uploading to gerrit, remote branch to ' | 1263 help='When uploading to gerrit, remote branch to ' |
1253 'use for CL. Default: master') | 1264 'use for CL. Default: master') |
1254 add_git_similarity(parser) | 1265 add_git_similarity(parser) |
1255 (options, args) = parser.parse_args(args) | 1266 (options, args) = parser.parse_args(args) |
1256 | 1267 |
1257 if options.target_branch and not settings.GetIsGerrit(): | 1268 if options.target_branch and not settings.GetIsGerrit(): |
1258 parser.error('Use --target_branch for non gerrit repository.') | 1269 parser.error('Use --target_branch for non gerrit repository.') |
1259 | 1270 |
1260 # Print warning if the user used the -m/--message argument. This will soon | 1271 # Print warning if the user used the -m/--message argument. This will soon |
1261 # change to -t/--title. | 1272 # change to -t/--title. |
1262 if options.message: | 1273 if options.message: |
1263 print >> sys.stderr, ( | 1274 print >> sys.stderr, ( |
1264 '\nWARNING: Use -t or --title to set the title of the patchset.\n' | 1275 '\nWARNING: Use -t or --title to set the title of the patchset.\n' |
1265 'In the near future, -m or --message will send a message instead.\n' | 1276 'In the near future, -m or --message will send a message instead.\n' |
1266 'See http://goo.gl/JGg0Z for details.\n') | 1277 'See http://goo.gl/JGg0Z for details.\n') |
1267 | 1278 |
1268 if is_dirty_git_tree('upload'): | 1279 if is_dirty_git_tree('upload'): |
1269 return 1 | 1280 return 1 |
1270 | 1281 |
1282 options.reviewers = cleanup_list(options.reviewers) | |
1283 options.cc = cleanup_list(options.cc) | |
1284 | |
1271 cl = Changelist() | 1285 cl = Changelist() |
1272 if args: | 1286 if args: |
1273 # TODO(ukai): is it ok for gerrit case? | 1287 # TODO(ukai): is it ok for gerrit case? |
1274 base_branch = args[0] | 1288 base_branch = args[0] |
1275 else: | 1289 else: |
1276 # Default to diffing against common ancestor of upstream branch | 1290 # Default to diffing against common ancestor of upstream branch |
1277 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() | 1291 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
1278 args = [base_branch, 'HEAD'] | 1292 args = [base_branch, 'HEAD'] |
1279 | 1293 |
1280 # Apply watchlists on upload. | 1294 # Apply watchlists on upload. |
1281 change = cl.GetChange(base_branch, None) | 1295 change = cl.GetChange(base_branch, None) |
1282 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 1296 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
1283 files = [f.LocalPath() for f in change.AffectedFiles()] | 1297 files = [f.LocalPath() for f in change.AffectedFiles()] |
1284 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) | 1298 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) |
1285 | 1299 |
1286 if not options.bypass_hooks: | 1300 if not options.bypass_hooks: |
1287 hook_results = cl.RunHook(committing=False, | 1301 hook_results = cl.RunHook(committing=False, |
1288 may_prompt=not options.force, | 1302 may_prompt=not options.force, |
1289 verbose=options.verbose, | 1303 verbose=options.verbose, |
1290 change=change) | 1304 change=change) |
1291 if not hook_results.should_continue(): | 1305 if not hook_results.should_continue(): |
1292 return 1 | 1306 return 1 |
1293 if not options.reviewers and hook_results.reviewers: | 1307 if not options.reviewers and hook_results.reviewers: |
1294 options.reviewers = hook_results.reviewers | 1308 options.reviewers = hook_results.reviewers.split(',') |
1295 | 1309 |
1296 if cl.GetIssue(): | 1310 if cl.GetIssue(): |
1297 latest_patchset = cl.GetMostRecentPatchset(cl.GetIssue()) | 1311 latest_patchset = cl.GetMostRecentPatchset(cl.GetIssue()) |
1298 local_patchset = cl.GetPatchset() | 1312 local_patchset = cl.GetPatchset() |
1299 if latest_patchset and local_patchset and local_patchset != latest_patchset: | 1313 if latest_patchset and local_patchset and local_patchset != latest_patchset: |
1300 print ('The last upload made from this repository was patchset #%d but ' | 1314 print ('The last upload made from this repository was patchset #%d but ' |
1301 'the most recent patchset on the server is #%d.' | 1315 'the most recent patchset on the server is #%d.' |
1302 % (local_patchset, latest_patchset)) | 1316 % (local_patchset, latest_patchset)) |
1303 ask_for_data('About to upload; enter to confirm.') | 1317 ask_for_data('About to upload; enter to confirm.') |
1304 | 1318 |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1905 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1919 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1906 | 1920 |
1907 # Not a known command. Default to help. | 1921 # Not a known command. Default to help. |
1908 GenUsage(parser, 'help') | 1922 GenUsage(parser, 'help') |
1909 return CMDhelp(parser, argv) | 1923 return CMDhelp(parser, argv) |
1910 | 1924 |
1911 | 1925 |
1912 if __name__ == '__main__': | 1926 if __name__ == '__main__': |
1913 fix_encoding.fix_encoding() | 1927 fix_encoding.fix_encoding() |
1914 sys.exit(main(sys.argv[1:])) | 1928 sys.exit(main(sys.argv[1:])) |
OLD | NEW |