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

Side by Side Diff: git_cl.py

Issue 9264065: Add minimal Gerrit support to 'git cl config' and 'git cl upload' (Closed) Base URL: svn://chrome-svn/chrome/trunk/tools/depot_tools/
Patch Set: Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 # 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 logging 10 import logging
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 def __init__(self): 140 def __init__(self):
141 self.default_server = None 141 self.default_server = None
142 self.cc = None 142 self.cc = None
143 self.root = None 143 self.root = None
144 self.is_git_svn = None 144 self.is_git_svn = None
145 self.svn_branch = None 145 self.svn_branch = None
146 self.tree_status_url = None 146 self.tree_status_url = None
147 self.viewvc_url = None 147 self.viewvc_url = None
148 self.updated = False 148 self.updated = False
149 self.did_migrate_check = False 149 self.did_migrate_check = False
150 self.is_gerrit = False
Evan Martin 2012/01/31 19:07:56 Set this to None here...
ukai 2012/02/01 05:57:15 Done.
150 151
151 def LazyUpdateIfNeeded(self): 152 def LazyUpdateIfNeeded(self):
152 """Updates the settings from a codereview.settings file, if available.""" 153 """Updates the settings from a codereview.settings file, if available."""
153 if not self.updated: 154 if not self.updated:
154 cr_settings_file = FindCodereviewSettingsFile() 155 cr_settings_file = FindCodereviewSettingsFile()
155 if cr_settings_file: 156 if cr_settings_file:
156 LoadCodereviewSettingsFromFile(cr_settings_file) 157 LoadCodereviewSettingsFromFile(cr_settings_file)
157 self.updated = True 158 self.updated = True
158 159
159 def GetDefaultServerUrl(self, error_ok=False): 160 def GetDefaultServerUrl(self, error_ok=False):
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 258
258 def GetViewVCUrl(self): 259 def GetViewVCUrl(self):
259 if not self.viewvc_url: 260 if not self.viewvc_url:
260 self.viewvc_url = gclient_utils.UpgradeToHttps( 261 self.viewvc_url = gclient_utils.UpgradeToHttps(
261 self._GetConfig('rietveld.viewvc-url', error_ok=True)) 262 self._GetConfig('rietveld.viewvc-url', error_ok=True))
262 return self.viewvc_url 263 return self.viewvc_url
263 264
264 def GetDefaultCCList(self): 265 def GetDefaultCCList(self):
265 return self._GetConfig('rietveld.cc', error_ok=True) 266 return self._GetConfig('rietveld.cc', error_ok=True)
266 267
268 def GetIsGerrit(self):
269 """Return true if this repo is assosiated with gerrit code review system."""
270 if not self.is_gerrit:
271 self.is_gerrit = self._GetConfig('gerrit.host', error_ok=True)
Evan Martin 2012/01/31 19:07:56 ...so that here we can change this test to if se
ukai 2012/02/01 05:57:15 Done.
272 return self.is_gerrit
273
267 def _GetConfig(self, param, **kwargs): 274 def _GetConfig(self, param, **kwargs):
268 self.LazyUpdateIfNeeded() 275 self.LazyUpdateIfNeeded()
269 return RunGit(['config', param], **kwargs).strip() 276 return RunGit(['config', param], **kwargs).strip()
270 277
271 278
272 def CheckForMigration(): 279 def CheckForMigration():
273 """Migrate from the old issue format, if found. 280 """Migrate from the old issue format, if found.
274 281
275 We used to store the branch<->issue mapping in a file in .git, but it's 282 We used to store the branch<->issue mapping in a file in .git, but it's
276 better to store it in the .git/config, since deleting a branch deletes that 283 better to store it in the .git/config, since deleting a branch deletes that
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 """Return the git setting that stores this change's most recent patchset.""" 604 """Return the git setting that stores this change's most recent patchset."""
598 return 'branch.%s.rietveldpatchset' % self.GetBranch() 605 return 'branch.%s.rietveldpatchset' % self.GetBranch()
599 606
600 def _RietveldServer(self): 607 def _RietveldServer(self):
601 """Returns the git setting that stores this change's rietveld server.""" 608 """Returns the git setting that stores this change's rietveld server."""
602 return 'branch.%s.rietveldserver' % self.GetBranch() 609 return 'branch.%s.rietveldserver' % self.GetBranch()
603 610
604 611
605 def GetCodereviewSettingsInteractively(): 612 def GetCodereviewSettingsInteractively():
606 """Prompt the user for settings.""" 613 """Prompt the user for settings."""
614 # TODO(ukai): ask code review system is rietveld or gerrit?
607 server = settings.GetDefaultServerUrl(error_ok=True) 615 server = settings.GetDefaultServerUrl(error_ok=True)
608 prompt = 'Rietveld server (host[:port])' 616 prompt = 'Rietveld server (host[:port])'
609 prompt += ' [%s]' % (server or DEFAULT_SERVER) 617 prompt += ' [%s]' % (server or DEFAULT_SERVER)
610 newserver = ask_for_data(prompt + ':') 618 newserver = ask_for_data(prompt + ':')
611 if not server and not newserver: 619 if not server and not newserver:
612 newserver = DEFAULT_SERVER 620 newserver = DEFAULT_SERVER
613 if newserver: 621 if newserver:
614 newserver = gclient_utils.UpgradeToHttps(newserver) 622 newserver = gclient_utils.UpgradeToHttps(newserver)
615 if newserver != server: 623 if newserver != server:
616 RunGit(['config', 'rietveld.server', newserver]) 624 RunGit(['config', 'rietveld.server', newserver])
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 else: 724 else:
717 RunGit(['config', '--unset-all', fullname], error_ok=unset_error_ok) 725 RunGit(['config', '--unset-all', fullname], error_ok=unset_error_ok)
718 726
719 SetProperty('server', 'CODE_REVIEW_SERVER') 727 SetProperty('server', 'CODE_REVIEW_SERVER')
720 # Only server setting is required. Other settings can be absent. 728 # Only server setting is required. Other settings can be absent.
721 # In that case, we ignore errors raised during option deletion attempt. 729 # In that case, we ignore errors raised during option deletion attempt.
722 SetProperty('cc', 'CC_LIST', unset_error_ok=True) 730 SetProperty('cc', 'CC_LIST', unset_error_ok=True)
723 SetProperty('tree-status-url', 'STATUS', unset_error_ok=True) 731 SetProperty('tree-status-url', 'STATUS', unset_error_ok=True)
724 SetProperty('viewvc-url', 'VIEW_VC', unset_error_ok=True) 732 SetProperty('viewvc-url', 'VIEW_VC', unset_error_ok=True)
725 733
734 if 'GERRIT_HOST' in keyvals and 'GERRIT_PORT' in keyvals:
735 RunGit(['config', 'gerrit.host', keyvals['GERRIT_HOST']])
736 RunGit(['config', 'gerrit.port', keyvals['GERRIT_PORT']])
737 # Install the standard commit-msg hook.
738 RunCommand(['scp', '-p', '-P', keyvals['GERRIT_PORT'],
739 '%s:hooks/commit-msg' % keyvals['GERRIT_HOST'],
740 os.path.join(settings.GetRoot(),
741 '.git', 'hooks', 'commit-msg')])
742
726 if 'PUSH_URL_CONFIG' in keyvals and 'ORIGIN_URL_CONFIG' in keyvals: 743 if 'PUSH_URL_CONFIG' in keyvals and 'ORIGIN_URL_CONFIG' in keyvals:
727 #should be of the form 744 #should be of the form
728 #PUSH_URL_CONFIG: url.ssh://gitrw.chromium.org.pushinsteadof 745 #PUSH_URL_CONFIG: url.ssh://gitrw.chromium.org.pushinsteadof
729 #ORIGIN_URL_CONFIG: http://src.chromium.org/git 746 #ORIGIN_URL_CONFIG: http://src.chromium.org/git
730 RunGit(['config', keyvals['PUSH_URL_CONFIG'], 747 RunGit(['config', keyvals['PUSH_URL_CONFIG'],
731 keyvals['ORIGIN_URL_CONFIG']]) 748 keyvals['ORIGIN_URL_CONFIG']])
732 749
733 750
734 @usage('[repo root containing codereview.settings]') 751 @usage('[repo root containing codereview.settings]')
735 def CMDconfig(parser, args): 752 def CMDconfig(parser, args):
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 else: 873 else:
857 # Default to diffing against the "upstream" branch. 874 # Default to diffing against the "upstream" branch.
858 base_branch = cl.GetUpstreamBranch() 875 base_branch = cl.GetUpstreamBranch()
859 876
860 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, 877 cl.RunHook(committing=not options.upload, upstream_branch=base_branch,
861 may_prompt=False, verbose=options.verbose, 878 may_prompt=False, verbose=options.verbose,
862 author=None) 879 author=None)
863 return 0 880 return 0
864 881
865 882
883 def GerritUpload(options, args, cl):
884 """upload the current branch to gerrit."""
885 # We assume the remote called "origin" is the one we want.
886 # It is probably not worthwhile to support different workflows.
887 remote = 'origin'
888 branch = 'master'
889 if args:
890 branch = args[0]
891
892 description = RunCommand(['git', 'log', '--pretty=format:%s%n%n%b',
893 '%s...' % (branch)]).strip()
894
895 receive_options = []
896 cc = []
897 if options.cc:
898 cc = options.cc.split(',')
899 cc = filter(None, (cl.GetCCList(), cc))
900 if cc:
901 receive_options += ['--cc=' + email for email in cc]
902 # Retrieves all reviewer lines
903 reviewer_regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE)
904 reviewers = ','.join(
905 i.group(2).strip()
906 for i in reviewer_regexp.finditer(description)).split(',')
907 print reviewers
Evan Martin 2012/01/31 19:07:56 Probably don't mean to print here.
ukai 2012/02/01 05:57:15 Done.
908 if options.reviewers:
909 reviewers = options.reviewers.split(',')
910 if reviewers:
911 receive_options += ['--reviewer=' + email for email in reviewers]
912
913 git_command = ['push']
914 if receive_options:
915 git_command.append('--receive-pack=git receive-pack ' +
Evan Martin 2012/01/31 19:07:56 This has a space in the argument. I don't think it
Roland McGrath 2012/01/31 19:24:21 No, it has to be this way.
ukai 2012/02/01 05:57:15 we pass "git receive-pack --reviewer=.." as value
916 ' '.join(receive_options))
917 git_command += [remote, 'HEAD:refs/for/' + branch]
918 RunGit(git_command)
919 return 0
920
921
866 @usage('[args to "git diff"]') 922 @usage('[args to "git diff"]')
867 def CMDupload(parser, args): 923 def CMDupload(parser, args):
868 """upload the current changelist to codereview""" 924 """upload the current changelist to codereview"""
869 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', 925 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks',
870 help='bypass upload presubmit hook') 926 help='bypass upload presubmit hook')
871 parser.add_option('-f', action='store_true', dest='force', 927 parser.add_option('-f', action='store_true', dest='force',
872 help="force yes to questions (don't prompt)") 928 help="force yes to questions (don't prompt)")
873 parser.add_option('-m', dest='message', help='message for patch') 929 parser.add_option('-m', dest='message', help='message for patch')
874 parser.add_option('-r', '--reviewers', 930 parser.add_option('-r', '--reviewers',
875 help='reviewer email addresses') 931 help='reviewer email addresses')
(...skipping 13 matching lines...) Expand all
889 (options, args) = parser.parse_args(args) 945 (options, args) = parser.parse_args(args)
890 946
891 # Make sure index is up-to-date before running diff-index. 947 # Make sure index is up-to-date before running diff-index.
892 RunGit(['update-index', '--refresh', '-q'], error_ok=True) 948 RunGit(['update-index', '--refresh', '-q'], error_ok=True)
893 if RunGit(['diff-index', 'HEAD']): 949 if RunGit(['diff-index', 'HEAD']):
894 print 'Cannot upload with a dirty tree. You must commit locally first.' 950 print 'Cannot upload with a dirty tree. You must commit locally first.'
895 return 1 951 return 1
896 952
897 cl = Changelist() 953 cl = Changelist()
898 if args: 954 if args:
955 # TODO(ukai): is it ok for gerrit case?
899 base_branch = args[0] 956 base_branch = args[0]
900 else: 957 else:
901 # Default to diffing against the "upstream" branch. 958 # Default to diffing against the "upstream" branch.
902 base_branch = cl.GetUpstreamBranch() 959 base_branch = cl.GetUpstreamBranch()
903 args = [base_branch + "..."] 960 if settings.GetIsGerrit():
961 args = ['master']
962 else:
963 args = [base_branch + "..."]
904 964
905 if not options.bypass_hooks: 965 if not options.bypass_hooks:
906 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, 966 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch,
907 may_prompt=not options.force, 967 may_prompt=not options.force,
908 verbose=options.verbose, 968 verbose=options.verbose,
909 author=None) 969 author=None)
910 if not hook_results.should_continue(): 970 if not hook_results.should_continue():
911 return 1 971 return 1
912 if not options.reviewers and hook_results.reviewers: 972 if not options.reviewers and hook_results.reviewers:
913 options.reviewers = hook_results.reviewers 973 options.reviewers = hook_results.reviewers
914 974
915 # --no-ext-diff is broken in some versions of Git, so try to work around 975 # --no-ext-diff is broken in some versions of Git, so try to work around
916 # this by overriding the environment (but there is still a problem if the 976 # this by overriding the environment (but there is still a problem if the
917 # git config key "diff.external" is used). 977 # git config key "diff.external" is used).
918 env = os.environ.copy() 978 env = os.environ.copy()
919 if 'GIT_EXTERNAL_DIFF' in env: 979 if 'GIT_EXTERNAL_DIFF' in env:
920 del env['GIT_EXTERNAL_DIFF'] 980 del env['GIT_EXTERNAL_DIFF']
921 subprocess2.call( 981 subprocess2.call(
922 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env) 982 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env)
923 983
984 if settings.GetIsGerrit():
985 GerritUpload(options, args, cl)
986 # TODO(ukai): parse Change-Id: and set issue number?
987 return 0
988
924 upload_args = ['--assume_yes'] # Don't ask about untracked files. 989 upload_args = ['--assume_yes'] # Don't ask about untracked files.
925 upload_args.extend(['--server', cl.GetRietveldServer()]) 990 upload_args.extend(['--server', cl.GetRietveldServer()])
926 if options.emulate_svn_auto_props: 991 if options.emulate_svn_auto_props:
927 upload_args.append('--emulate_svn_auto_props') 992 upload_args.append('--emulate_svn_auto_props')
928 if options.from_logs and not options.message: 993 if options.from_logs and not options.message:
929 print 'Must set message for subject line if using desc_from_logs' 994 print 'Must set message for subject line if using desc_from_logs'
930 return 1 995 return 1
931 996
932 change_desc = None 997 change_desc = None
933 998
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 help='allow failed patches and spew .rej files') 1287 help='allow failed patches and spew .rej files')
1223 parser.add_option('-n', '--no-commit', action='store_true', dest='nocommit', 1288 parser.add_option('-n', '--no-commit', action='store_true', dest='nocommit',
1224 help="don't commit after patch applies") 1289 help="don't commit after patch applies")
1225 (options, args) = parser.parse_args(args) 1290 (options, args) = parser.parse_args(args)
1226 if len(args) != 1: 1291 if len(args) != 1:
1227 parser.print_help() 1292 parser.print_help()
1228 return 1 1293 return 1
1229 issue_arg = args[0] 1294 issue_arg = args[0]
1230 1295
1231 # TODO(maruel): Use apply_issue.py 1296 # TODO(maruel): Use apply_issue.py
1297 # TODO(ukai): use gerrit-cherry-pick for gerrit repository?
1232 1298
1233 if re.match(r'\d+', issue_arg): 1299 if re.match(r'\d+', issue_arg):
1234 # Input is an issue id. Figure out the URL. 1300 # Input is an issue id. Figure out the URL.
1235 issue = issue_arg 1301 issue = issue_arg
1236 patch_data = Changelist().GetPatchSetDiff(issue) 1302 patch_data = Changelist().GetPatchSetDiff(issue)
1237 else: 1303 else:
1238 # Assume it's a URL to the patch. Default to https. 1304 # Assume it's a URL to the patch. Default to https.
1239 issue_url = gclient_utils.UpgradeToHttps(issue_arg) 1305 issue_url = gclient_utils.UpgradeToHttps(issue_arg)
1240 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url) 1306 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url)
1241 if not match: 1307 if not match:
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) 1494 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)))
1429 1495
1430 # Not a known command. Default to help. 1496 # Not a known command. Default to help.
1431 GenUsage(parser, 'help') 1497 GenUsage(parser, 'help')
1432 return CMDhelp(parser, argv) 1498 return CMDhelp(parser, argv)
1433 1499
1434 1500
1435 if __name__ == '__main__': 1501 if __name__ == '__main__':
1436 fix_encoding.fix_encoding() 1502 fix_encoding.fix_encoding()
1437 sys.exit(main(sys.argv[1:])) 1503 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698