Commit aa6235b1 authored by tandrii@chromium.org's avatar tandrii@chromium.org

Refactor git cl RietveldUpload and GerritUpload.

No functionality changes.

R=machenbach@chromium.org,andybons@chromium.org
BUG=579160,597638

Review URL: https://codereview.chromium.org/1877893002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@299844 0039d316-1c4b-4281-b951-d872f2087c98
parent 26c8fd2b
...@@ -1426,6 +1426,10 @@ class _ChangelistCodereviewBase(object): ...@@ -1426,6 +1426,10 @@ class _ChangelistCodereviewBase(object):
failed.""" failed."""
raise NotImplementedError() raise NotImplementedError()
def CMDUploadChange(self, options, args, change):
"""Uploads a change to codereview."""
raise NotImplementedError()
class _RietveldChangelistImpl(_ChangelistCodereviewBase): class _RietveldChangelistImpl(_ChangelistCodereviewBase):
def __init__(self, changelist, auth_config=None, rietveld_server=None): def __init__(self, changelist, auth_config=None, rietveld_server=None):
...@@ -1438,9 +1442,6 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase): ...@@ -1438,9 +1442,6 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
self._props = None self._props = None
self._rpc_server = None self._rpc_server = None
def GetAuthConfig(self):
return self._auth_config
def GetCodereviewServer(self): def GetCodereviewServer(self):
if not self._rietveld_server: if not self._rietveld_server:
# If we're on a branch then get the server potentially associated # If we're on a branch then get the server potentially associated
...@@ -1687,6 +1688,158 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase): ...@@ -1687,6 +1688,158 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
patch_url=gclient_utils.UpgradeToHttps(parsed_url.geturl())) patch_url=gclient_utils.UpgradeToHttps(parsed_url.geturl()))
return None return None
def CMDUploadChange(self, options, args, change):
"""Upload the patch to Rietveld."""
upload_args = ['--assume_yes'] # Don't ask about untracked files.
upload_args.extend(['--server', self.GetCodereviewServer()])
# TODO(tandrii): refactor this ugliness into _RietveldChangelistImpl.
upload_args.extend(auth.auth_config_to_command_options(self._auth_config))
if options.emulate_svn_auto_props:
upload_args.append('--emulate_svn_auto_props')
change_desc = None
if options.email is not None:
upload_args.extend(['--email', options.email])
if self.GetIssue():
if options.title:
upload_args.extend(['--title', options.title])
if options.message:
upload_args.extend(['--message', options.message])
upload_args.extend(['--issue', str(self.GetIssue())])
print ('This branch is associated with issue %s. '
'Adding patch to that issue.' % self.GetIssue())
else:
if options.title:
upload_args.extend(['--title', options.title])
message = (options.title or options.message or
CreateDescriptionFromLog(args))
change_desc = ChangeDescription(message)
if options.reviewers or options.tbr_owners:
change_desc.update_reviewers(options.reviewers,
options.tbr_owners,
change)
if not options.force:
change_desc.prompt()
if not change_desc.description:
print "Description is empty; aborting."
return 1
upload_args.extend(['--message', change_desc.description])
if change_desc.get_reviewers():
upload_args.append('--reviewers=%s' % ','.join(
change_desc.get_reviewers()))
if options.send_mail:
if not change_desc.get_reviewers():
DieWithError("Must specify reviewers to send email.")
upload_args.append('--send_mail')
# We check this before applying rietveld.private assuming that in
# rietveld.cc only addresses which we can send private CLs to are listed
# if rietveld.private is set, and so we should ignore rietveld.cc only
# when --private is specified explicitly on the command line.
if options.private:
logging.warn('rietveld.cc is ignored since private flag is specified. '
'You need to review and add them manually if necessary.')
cc = self.GetCCListWithoutDefault()
else:
cc = self.GetCCList()
cc = ','.join(filter(None, (cc, ','.join(options.cc))))
if cc:
upload_args.extend(['--cc', cc])
if options.private or settings.GetDefaultPrivateFlag() == "True":
upload_args.append('--private')
upload_args.extend(['--git_similarity', str(options.similarity)])
if not options.find_copies:
upload_args.extend(['--git_no_find_copies'])
# Include the upstream repo's URL in the change -- this is useful for
# projects that have their source spread across multiple repos.
remote_url = self.GetGitBaseUrlFromConfig()
if not remote_url:
if settings.GetIsGitSvn():
remote_url = self.GetGitSvnRemoteUrl()
else:
if self.GetRemoteUrl() and '/' in self.GetUpstreamBranch():
remote_url = '%s@%s' % (self.GetRemoteUrl(),
self.GetUpstreamBranch().split('/')[-1])
if remote_url:
upload_args.extend(['--base_url', remote_url])
remote, remote_branch = self.GetRemoteBranch()
target_ref = GetTargetRef(remote, remote_branch, options.target_branch,
settings.GetPendingRefPrefix())
if target_ref:
upload_args.extend(['--target_ref', target_ref])
# Look for dependent patchsets. See crbug.com/480453 for more details.
remote, upstream_branch = self.FetchUpstreamTuple(self.GetBranch())
upstream_branch = ShortBranchName(upstream_branch)
if remote is '.':
# A local branch is being tracked.
local_branch = ShortBranchName(upstream_branch)
if settings.GetIsSkipDependencyUpload(local_branch):
print
print ('Skipping dependency patchset upload because git config '
'branch.%s.skip-deps-uploads is set to True.' % local_branch)
print
else:
auth_config = auth.extract_auth_config_from_options(options)
branch_cl = Changelist(branchref=local_branch,
auth_config=auth_config)
branch_cl_issue_url = branch_cl.GetIssueURL()
branch_cl_issue = branch_cl.GetIssue()
branch_cl_patchset = branch_cl.GetPatchset()
if branch_cl_issue_url and branch_cl_issue and branch_cl_patchset:
upload_args.extend(
['--depends_on_patchset', '%s:%s' % (
branch_cl_issue, branch_cl_patchset)])
print (
'\n'
'The current branch (%s) is tracking a local branch (%s) with '
'an associated CL.\n'
'Adding %s/#ps%s as a dependency patchset.\n'
'\n' % (self.GetBranch(), local_branch, branch_cl_issue_url,
branch_cl_patchset))
project = settings.GetProject()
if project:
upload_args.extend(['--project', project])
if options.cq_dry_run:
upload_args.extend(['--cq_dry_run'])
try:
upload_args = ['upload'] + upload_args + args
logging.info('upload.RealMain(%s)', upload_args)
issue, patchset = upload.RealMain(upload_args)
issue = int(issue)
patchset = int(patchset)
except KeyboardInterrupt:
sys.exit(1)
except:
# If we got an exception after the user typed a description for their
# change, back up the description before re-raising.
if change_desc:
backup_path = os.path.expanduser(DESCRIPTION_BACKUP_FILE)
print('\nGot exception while uploading -- saving description to %s\n' %
backup_path)
backup_file = open(backup_path, 'w')
backup_file.write(change_desc.description)
backup_file.close()
raise
if not self.GetIssue():
self.SetIssue(issue)
self.SetPatchset(patchset)
if options.use_commit_queue:
self.SetFlag('commit', '1')
return 0
class _GerritChangelistImpl(_ChangelistCodereviewBase): class _GerritChangelistImpl(_ChangelistCodereviewBase):
def __init__(self, changelist, auth_config=None): def __init__(self, changelist, auth_config=None):
...@@ -1826,9 +1979,11 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase): ...@@ -1826,9 +1979,11 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase):
gerrit_util.SubmitChange(self._GetGerritHost(), self.GetIssue(), gerrit_util.SubmitChange(self._GetGerritHost(), self.GetIssue(),
wait_for_merge=wait_for_merge) wait_for_merge=wait_for_merge)
def _GetChangeDetail(self, options): def _GetChangeDetail(self, options=None, issue=None):
return gerrit_util.GetChangeDetail(self._GetGerritHost(), self.GetIssue(), options = options or []
options) issue = issue or self.GetIssue()
assert issue, 'issue required to query Gerrit'
return gerrit_util.GetChangeDetail(self._GetGerritHost(), options, issue)
def CMDLand(self, force, bypass_hooks, verbose): def CMDLand(self, force, bypass_hooks, verbose):
if git_common.is_dirty_git_tree('land'): if git_common.is_dirty_git_tree('land'):
...@@ -1922,41 +2077,241 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase): ...@@ -1922,41 +2077,241 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase):
hostname=parsed_url.netloc) hostname=parsed_url.netloc)
return None return None
def CMDUploadChange(self, options, args, change):
"""Upload the current branch to Gerrit."""
# We assume the remote called "origin" is the one we want.
# It is probably not worthwhile to support different workflows.
gerrit_remote = 'origin'
_CODEREVIEW_IMPLEMENTATIONS = { remote, remote_branch = self.GetRemoteBranch()
'rietveld': _RietveldChangelistImpl, branch = GetTargetRef(remote, remote_branch, options.target_branch,
'gerrit': _GerritChangelistImpl, pending_prefix='')
}
if options.title:
# TODO(tandrii): it's now supported by Gerrit, implement!
print "\nPatch titles (-t) are not supported in Gerrit. Aborting..."
return 1
class ChangeDescription(object): if options.squash:
"""Contains a parsed form of the change description.""" if not self.GetIssue():
R_LINE = r'^[ \t]*(TBR|R)[ \t]*=[ \t]*(.*?)[ \t]*$' # TODO(tandrii): deperecate this after 2016Q2. Backwards compatibility
BUG_LINE = r'^[ \t]*(BUG)[ \t]*=[ \t]*(.*?)[ \t]*$' # with shadow branch, which used to contain change-id for a given
# branch, using which we can fetch actual issue number and set it as the
# property of the branch, which is the new way.
message = RunGitSilent([
'show', '--format=%B', '-s',
'refs/heads/git_cl_uploads/%s' % self.GetBranch()])
if message:
change_ids = git_footers.get_footer_change_id(message.strip())
if change_ids and len(change_ids) == 1:
details = self._GetChangeDetail(issue=change_ids[0])
if details:
print('WARNING: found old upload in branch git_cl_uploads/%s '
'corresponding to issue %s' %
(self.GetBranch(), details['_number']))
self.SetIssue(details['_number'])
if not self.GetIssue():
DieWithError(
'\n' # For readability of the blob below.
'Found old upload in branch git_cl_uploads/%s, '
'but failed to find corresponding Gerrit issue.\n'
'If you know the issue number, set it manually first:\n'
' git cl issue 123456\n'
'If you intended to upload this CL as new issue, '
'just delete or rename the old upload branch:\n'
' git rename-branch git_cl_uploads/%s old_upload-%s\n'
'After that, please run git cl upload again.' %
tuple([self.GetBranch()] * 3))
# End of backwards compatability.
def __init__(self, description): if self.GetIssue():
self._description_lines = (description or '').strip().splitlines() # Try to get the message from a previous upload.
message = self.GetDescription()
if not message:
DieWithError(
'failed to fetch description from current Gerrit issue %d\n'
'%s' % (self.GetIssue(), self.GetIssueURL()))
change_id = self._GetChangeDetail()['change_id']
while True:
footer_change_ids = git_footers.get_footer_change_id(message)
if footer_change_ids == [change_id]:
break
if not footer_change_ids:
message = git_footers.add_footer_change_id(message, change_id)
print('WARNING: appended missing Change-Id to issue description')
continue
# There is already a valid footer but with different or several ids.
# Doing this automatically is non-trivial as we don't want to lose
# existing other footers, yet we want to append just 1 desired
# Change-Id. Thus, just create a new footer, but let user verify the
# new description.
message = '%s\n\nChange-Id: %s' % (message, change_id)
print(
'WARNING: issue %s has Change-Id footer(s):\n'
' %s\n'
'but issue has Change-Id %s, according to Gerrit.\n'
'Please, check the proposed correction to the description, '
'and edit it if necessary but keep the "Change-Id: %s" footer\n'
% (self.GetIssue(), '\n '.join(footer_change_ids), change_id,
change_id))
ask_for_data('Press enter to edit now, Ctrl+C to abort')
if not options.force:
change_desc = ChangeDescription(message)
change_desc.prompt()
message = change_desc.description
if not message:
DieWithError("Description is empty. Aborting...")
# Continue the while loop.
# Sanity check of this code - we should end up with proper message
# footer.
assert [change_id] == git_footers.get_footer_change_id(message)
change_desc = ChangeDescription(message)
else:
change_desc = ChangeDescription(
options.message or CreateDescriptionFromLog(args))
if not options.force:
change_desc.prompt()
if not change_desc.description:
DieWithError("Description is empty. Aborting...")
message = change_desc.description
change_ids = git_footers.get_footer_change_id(message)
if len(change_ids) > 1:
DieWithError('too many Change-Id footers, at most 1 allowed.')
if not change_ids:
# Generate the Change-Id automatically.
message = git_footers.add_footer_change_id(
message, GenerateGerritChangeId(message))
change_desc.set_description(message)
change_ids = git_footers.get_footer_change_id(message)
assert len(change_ids) == 1
change_id = change_ids[0]
@property # www.logilab.org/ticket/89786 remote, upstream_branch = self.FetchUpstreamTuple(self.GetBranch())
def description(self): # pylint: disable=E0202 if remote is '.':
return '\n'.join(self._description_lines) # If our upstream branch is local, we base our squashed commit on its
# squashed version.
upstream_branch_name = scm.GIT.ShortBranchName(upstream_branch)
# Check the squashed hash of the parent.
parent = RunGit(['config',
'branch.%s.gerritsquashhash' % upstream_branch_name],
error_ok=True).strip()
# Verify that the upstream branch has been uploaded too, otherwise
# Gerrit will create additional CLs when uploading.
if not parent or (RunGitSilent(['rev-parse', upstream_branch + ':']) !=
RunGitSilent(['rev-parse', parent + ':'])):
# TODO(tandrii): remove "old depot_tools" part on April 12, 2016.
DieWithError(
'Upload upstream branch %s first.\n'
'Note: maybe you\'ve uploaded it with --no-squash or with an old '
'version of depot_tools. If so, then re-upload it with:\n'
' git cl upload --squash\n' % upstream_branch_name)
else:
parent = self.GetCommonAncestorWithUpstream()
def set_description(self, desc): tree = RunGit(['rev-parse', 'HEAD:']).strip()
if isinstance(desc, basestring): ref_to_push = RunGit(['commit-tree', tree, '-p', parent,
lines = desc.splitlines() '-m', message]).strip()
else: else:
lines = [line.rstrip() for line in desc] change_desc = ChangeDescription(
while lines and not lines[0]: options.message or CreateDescriptionFromLog(args))
lines.pop(0) if not change_desc.description:
while lines and not lines[-1]: DieWithError("Description is empty. Aborting...")
lines.pop(-1)
self._description_lines = lines
def update_reviewers(self, reviewers, add_owners_tbr=False, change=None): if not git_footers.get_footer_change_id(change_desc.description):
"""Rewrites the R=/TBR= line(s) as a single line each.""" DownloadGerritHook(False)
assert isinstance(reviewers, list), reviewers change_desc.set_description(AddChangeIdToCommitMessage(options, args))
if not reviewers and not add_owners_tbr: ref_to_push = 'HEAD'
return parent = '%s/%s' % (gerrit_remote, branch)
change_id = git_footers.get_footer_change_id(change_desc.description)[0]
assert change_desc
commits = RunGitSilent(['rev-list', '%s..%s' % (parent,
ref_to_push)]).splitlines()
if len(commits) > 1:
print('WARNING: This will upload %d commits. Run the following command '
'to see which commits will be uploaded: ' % len(commits))
print('git log %s..%s' % (parent, ref_to_push))
print('You can also use `git squash-branch` to squash these into a '
'single commit.')
ask_for_data('About to upload; enter to confirm.')
if options.reviewers or options.tbr_owners:
change_desc.update_reviewers(options.reviewers, options.tbr_owners,
change)
receive_options = []
cc = self.GetCCList().split(',')
if options.cc:
cc.extend(options.cc)
cc = filter(None, cc)
if cc:
receive_options += ['--cc=' + email for email in cc]
if change_desc.get_reviewers():
receive_options.extend(
'--reviewer=' + email for email in change_desc.get_reviewers())
git_command = ['push']
if receive_options:
git_command.append('--receive-pack=git receive-pack %s' %
' '.join(receive_options))
git_command += [gerrit_remote, ref_to_push + ':refs/for/' + branch]
push_stdout = gclient_utils.CheckCallAndFilter(
['git'] + git_command,
print_stdout=True,
# Flush after every line: useful for seeing progress when running as
# recipe.
filter_fn=lambda _: sys.stdout.flush())
if options.squash:
regex = re.compile(r'remote:\s+https?://[\w\-\.\/]*/(\d+)\s.*')
change_numbers = [m.group(1)
for m in map(regex.match, push_stdout.splitlines())
if m]
if len(change_numbers) != 1:
DieWithError(
('Created|Updated %d issues on Gerrit, but only 1 expected.\n'
'Change-Id: %s') % (len(change_numbers), change_id))
self.SetIssue(change_numbers[0])
RunGit(['config', 'branch.%s.gerritsquashhash' % self.GetBranch(),
ref_to_push])
return 0
_CODEREVIEW_IMPLEMENTATIONS = {
'rietveld': _RietveldChangelistImpl,
'gerrit': _GerritChangelistImpl,
}
class ChangeDescription(object):
"""Contains a parsed form of the change description."""
R_LINE = r'^[ \t]*(TBR|R)[ \t]*=[ \t]*(.*?)[ \t]*$'
BUG_LINE = r'^[ \t]*(BUG)[ \t]*=[ \t]*(.*?)[ \t]*$'
def __init__(self, description):
self._description_lines = (description or '').strip().splitlines()
@property # www.logilab.org/ticket/89786
def description(self): # pylint: disable=E0202
return '\n'.join(self._description_lines)
def set_description(self, desc):
if isinstance(desc, basestring):
lines = desc.splitlines()
else:
lines = [line.rstrip() for line in desc]
while lines and not lines[0]:
lines.pop(0)
while lines and not lines[-1]:
lines.pop(-1)
self._description_lines = lines
def update_reviewers(self, reviewers, add_owners_tbr=False, change=None):
"""Rewrites the R=/TBR= line(s) as a single line each."""
assert isinstance(reviewers, list), reviewers
if not reviewers and not add_owners_tbr:
return
reviewers = reviewers[:] reviewers = reviewers[:]
# Get the set of R= and TBR= lines and remove them from the desciption. # Get the set of R= and TBR= lines and remove them from the desciption.
...@@ -2794,206 +3149,6 @@ def GenerateGerritChangeId(message): ...@@ -2794,206 +3149,6 @@ def GenerateGerritChangeId(message):
return 'I%s' % change_hash.strip() return 'I%s' % change_hash.strip()
def GerritUpload(options, args, cl, change):
"""upload the current branch to gerrit."""
# TODO(tandrii): refactor this to be a method of _GerritChangelistImpl,
# to avoid private members accessors below.
# We assume the remote called "origin" is the one we want.
# It is probably not worthwhile to support different workflows.
gerrit_remote = 'origin'
remote, remote_branch = cl.GetRemoteBranch()
branch = GetTargetRef(remote, remote_branch, options.target_branch,
pending_prefix='')
if options.title:
print "\nPatch titles (-t) are not supported in Gerrit. Aborting..."
return 1
if options.squash:
if not cl.GetIssue():
# TODO(tandrii): deperecate this after 2016Q2.
# Backwards compatibility with shadow branch, which used to contain
# change-id for a given branch, using which we can fetch actual issue
# number and set it as the property of the branch, which is the new way.
message = RunGitSilent(['show', '--format=%B', '-s',
'refs/heads/git_cl_uploads/%s' % cl.GetBranch()])
if message:
change_ids = git_footers.get_footer_change_id(message.strip())
if change_ids and len(change_ids) == 1:
details = gerrit_util.GetChangeDetail(
cl._codereview_impl._GetGerritHost(), change_ids[0])
if details:
print('WARNING: found old upload in branch git_cl_uploads/%s '
'corresponding to issue %s' %
(cl.GetBranch(), details['_number']))
cl.SetIssue(details['_number'])
if not cl.GetIssue():
DieWithError(
'\n' # For readability of the blob below.
'Found old upload in branch git_cl_uploads/%s, '
'but failed to find corresponding Gerrit issue.\n'
'If you know the issue number, set it manually first:\n'
' git cl issue 123456\n'
'If you intended to upload this CL as new issue, '
'just delete or rename the old upload branch:\n'
' git rename-branch git_cl_uploads/%s old_upload-%s\n'
'After that, please run git cl upload again.' %
tuple([cl.GetBranch()] * 3))
# End of backwards compatability.
if cl.GetIssue():
# Try to get the message from a previous upload.
message = cl.GetDescription()
if not message:
DieWithError(
'failed to fetch description from current Gerrit issue %d\n'
'%s' % (cl.GetIssue(), cl.GetIssueURL()))
change_id = cl._codereview_impl._GetChangeDetail([])['change_id']
while True:
footer_change_ids = git_footers.get_footer_change_id(message)
if footer_change_ids == [change_id]:
break
if not footer_change_ids:
message = git_footers.add_footer_change_id(message, change_id)
print('WARNING: appended missing Change-Id to issue description')
continue
# There is already a valid footer but with different or several ids.
# Doing this automatically is non-trivial as we don't want to lose
# existing other footers, yet we want to append just 1 desired
# Change-Id. Thus, just create a new footer, but let user verify the new
# description.
message = '%s\n\nChange-Id: %s' % (message, change_id)
print(
'WARNING: issue %s has Change-Id footer(s):\n'
' %s\n'
'but issue has Change-Id %s, according to Gerrit.\n'
'Please, check the proposed correction to the description, '
'and edit it if necessary but keep the "Change-Id: %s" footer\n'
% (cl.GetIssue(), '\n '.join(footer_change_ids), change_id,
change_id))
ask_for_data('Press enter to edit now, Ctrl+C to abort')
if not options.force:
change_desc = ChangeDescription(message)
change_desc.prompt()
message = change_desc.description
if not message:
DieWithError("Description is empty. Aborting...")
# Continue the while loop.
# Sanity check of this code - we should end up with proper message footer.
assert [change_id] == git_footers.get_footer_change_id(message)
change_desc = ChangeDescription(message)
else:
change_desc = ChangeDescription(
options.message or CreateDescriptionFromLog(args))
if not options.force:
change_desc.prompt()
if not change_desc.description:
DieWithError("Description is empty. Aborting...")
message = change_desc.description
change_ids = git_footers.get_footer_change_id(message)
if len(change_ids) > 1:
DieWithError('too many Change-Id footers, at most 1 allowed.')
if not change_ids:
# Generate the Change-Id automatically.
message = git_footers.add_footer_change_id(
message, GenerateGerritChangeId(message))
change_desc.set_description(message)
change_ids = git_footers.get_footer_change_id(message)
assert len(change_ids) == 1
change_id = change_ids[0]
remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch())
if remote is '.':
# If our upstream branch is local, we base our squashed commit on its
# squashed version.
upstream_branch_name = scm.GIT.ShortBranchName(upstream_branch)
# Check the squashed hash of the parent.
parent = RunGit(['config',
'branch.%s.gerritsquashhash' % upstream_branch_name],
error_ok=True).strip()
# Verify that the upstream branch has been uploaded too, otherwise
# Gerrit will create additional CLs when uploading.
if not parent or (RunGitSilent(['rev-parse', upstream_branch + ':']) !=
RunGitSilent(['rev-parse', parent + ':'])):
# TODO(tandrii): remove "old depot_tools" part on April 12, 2016.
DieWithError(
'Upload upstream branch %s first.\n'
'Note: maybe you\'ve uploaded it with --no-squash or with an old\n'
' version of depot_tools. If so, then re-upload it with:\n'
' git cl upload --squash\n' % upstream_branch_name)
else:
parent = cl.GetCommonAncestorWithUpstream()
tree = RunGit(['rev-parse', 'HEAD:']).strip()
ref_to_push = RunGit(['commit-tree', tree, '-p', parent,
'-m', message]).strip()
else:
change_desc = ChangeDescription(
options.message or CreateDescriptionFromLog(args))
if not change_desc.description:
DieWithError("Description is empty. Aborting...")
if not git_footers.get_footer_change_id(change_desc.description):
DownloadGerritHook(False)
change_desc.set_description(AddChangeIdToCommitMessage(options, args))
ref_to_push = 'HEAD'
parent = '%s/%s' % (gerrit_remote, branch)
change_id = git_footers.get_footer_change_id(change_desc.description)[0]
assert change_desc
commits = RunGitSilent(['rev-list', '%s..%s' % (parent,
ref_to_push)]).splitlines()
if len(commits) > 1:
print('WARNING: This will upload %d commits. Run the following command '
'to see which commits will be uploaded: ' % len(commits))
print('git log %s..%s' % (parent, ref_to_push))
print('You can also use `git squash-branch` to squash these into a single '
'commit.')
ask_for_data('About to upload; enter to confirm.')
if options.reviewers or options.tbr_owners:
change_desc.update_reviewers(options.reviewers, options.tbr_owners, change)
receive_options = []
cc = cl.GetCCList().split(',')
if options.cc:
cc.extend(options.cc)
cc = filter(None, cc)
if cc:
receive_options += ['--cc=' + email for email in cc]
if change_desc.get_reviewers():
receive_options.extend(
'--reviewer=' + email for email in change_desc.get_reviewers())
git_command = ['push']
if receive_options:
git_command.append('--receive-pack=git receive-pack %s' %
' '.join(receive_options))
git_command += [gerrit_remote, ref_to_push + ':refs/for/' + branch]
push_stdout = gclient_utils.CheckCallAndFilter(
['git'] + git_command,
print_stdout=True,
# Flush after every line: useful for seeing progress when running as
# recipe.
filter_fn=lambda _: sys.stdout.flush())
if options.squash:
regex = re.compile(r'remote:\s+https?://[\w\-\.\/]*/(\d+)\s.*')
change_numbers = [m.group(1)
for m in map(regex.match, push_stdout.splitlines())
if m]
if len(change_numbers) != 1:
DieWithError(
('Created|Updated %d issues on Gerrit, but only 1 expected.\n'
'Change-Id: %s') % (len(change_numbers), change_id))
cl.SetIssue(change_numbers[0])
RunGit(['config', 'branch.%s.gerritsquashhash' % cl.GetBranch(),
ref_to_push])
return 0
def GetTargetRef(remote, remote_branch, target_branch, pending_prefix): def GetTargetRef(remote, remote_branch, target_branch, pending_prefix):
"""Computes the remote branch ref to use for the CL. """Computes the remote branch ref to use for the CL.
...@@ -3049,156 +3204,6 @@ def GetTargetRef(remote, remote_branch, target_branch, pending_prefix): ...@@ -3049,156 +3204,6 @@ def GetTargetRef(remote, remote_branch, target_branch, pending_prefix):
return remote_branch return remote_branch
def RietveldUpload(options, args, cl, change):
"""upload the patch to rietveld."""
upload_args = ['--assume_yes'] # Don't ask about untracked files.
upload_args.extend(['--server', cl.GetCodereviewServer()])
# TODO(tandrii): refactor this ugliness into _RietveldChangelistImpl.
upload_args.extend(auth.auth_config_to_command_options(
cl._codereview_impl.GetAuthConfig()))
if options.emulate_svn_auto_props:
upload_args.append('--emulate_svn_auto_props')
change_desc = None
if options.email is not None:
upload_args.extend(['--email', options.email])
if cl.GetIssue():
if options.title:
upload_args.extend(['--title', options.title])
if options.message:
upload_args.extend(['--message', options.message])
upload_args.extend(['--issue', str(cl.GetIssue())])
print ("This branch is associated with issue %s. "
"Adding patch to that issue." % cl.GetIssue())
else:
if options.title:
upload_args.extend(['--title', options.title])
message = options.title or options.message or CreateDescriptionFromLog(args)
change_desc = ChangeDescription(message)
if options.reviewers or options.tbr_owners:
change_desc.update_reviewers(options.reviewers,
options.tbr_owners,
change)
if not options.force:
change_desc.prompt()
if not change_desc.description:
print "Description is empty; aborting."
return 1
upload_args.extend(['--message', change_desc.description])
if change_desc.get_reviewers():
upload_args.append('--reviewers=' + ','.join(change_desc.get_reviewers()))
if options.send_mail:
if not change_desc.get_reviewers():
DieWithError("Must specify reviewers to send email.")
upload_args.append('--send_mail')
# We check this before applying rietveld.private assuming that in
# rietveld.cc only addresses which we can send private CLs to are listed
# if rietveld.private is set, and so we should ignore rietveld.cc only when
# --private is specified explicitly on the command line.
if options.private:
logging.warn('rietveld.cc is ignored since private flag is specified. '
'You need to review and add them manually if necessary.')
cc = cl.GetCCListWithoutDefault()
else:
cc = cl.GetCCList()
cc = ','.join(filter(None, (cc, ','.join(options.cc))))
if cc:
upload_args.extend(['--cc', cc])
if options.private or settings.GetDefaultPrivateFlag() == "True":
upload_args.append('--private')
upload_args.extend(['--git_similarity', str(options.similarity)])
if not options.find_copies:
upload_args.extend(['--git_no_find_copies'])
# Include the upstream repo's URL in the change -- this is useful for
# projects that have their source spread across multiple repos.
remote_url = cl.GetGitBaseUrlFromConfig()
if not remote_url:
if settings.GetIsGitSvn():
remote_url = cl.GetGitSvnRemoteUrl()
else:
if cl.GetRemoteUrl() and '/' in cl.GetUpstreamBranch():
remote_url = (cl.GetRemoteUrl() + '@'
+ cl.GetUpstreamBranch().split('/')[-1])
if remote_url:
upload_args.extend(['--base_url', remote_url])
remote, remote_branch = cl.GetRemoteBranch()
target_ref = GetTargetRef(remote, remote_branch, options.target_branch,
settings.GetPendingRefPrefix())
if target_ref:
upload_args.extend(['--target_ref', target_ref])
# Look for dependent patchsets. See crbug.com/480453 for more details.
remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch())
upstream_branch = ShortBranchName(upstream_branch)
if remote is '.':
# A local branch is being tracked.
local_branch = ShortBranchName(upstream_branch)
if settings.GetIsSkipDependencyUpload(local_branch):
print
print ('Skipping dependency patchset upload because git config '
'branch.%s.skip-deps-uploads is set to True.' % local_branch)
print
else:
auth_config = auth.extract_auth_config_from_options(options)
branch_cl = Changelist(branchref=local_branch, auth_config=auth_config)
branch_cl_issue_url = branch_cl.GetIssueURL()
branch_cl_issue = branch_cl.GetIssue()
branch_cl_patchset = branch_cl.GetPatchset()
if branch_cl_issue_url and branch_cl_issue and branch_cl_patchset:
upload_args.extend(
['--depends_on_patchset', '%s:%s' % (
branch_cl_issue, branch_cl_patchset)])
print
print ('The current branch (%s) is tracking a local branch (%s) with '
'an associated CL.') % (cl.GetBranch(), local_branch)
print 'Adding %s/#ps%s as a dependency patchset.' % (
branch_cl_issue_url, branch_cl_patchset)
print
project = settings.GetProject()
if project:
upload_args.extend(['--project', project])
if options.cq_dry_run:
upload_args.extend(['--cq_dry_run'])
try:
upload_args = ['upload'] + upload_args + args
logging.info('upload.RealMain(%s)', upload_args)
issue, patchset = upload.RealMain(upload_args)
issue = int(issue)
patchset = int(patchset)
except KeyboardInterrupt:
sys.exit(1)
except:
# If we got an exception after the user typed a description for their
# change, back up the description before re-raising.
if change_desc:
backup_path = os.path.expanduser(DESCRIPTION_BACKUP_FILE)
print '\nGot exception while uploading -- saving description to %s\n' \
% backup_path
backup_file = open(backup_path, 'w')
backup_file.write(change_desc.description)
backup_file.close()
raise
if not cl.GetIssue():
cl.SetIssue(issue)
cl.SetPatchset(patchset)
if options.use_commit_queue:
cl.SetFlag('commit', '1')
return 0
def cleanup_list(l): def cleanup_list(l):
"""Fixes a list so that comma separated items are put as individual items. """Fixes a list so that comma separated items are put as individual items.
...@@ -3349,9 +3354,7 @@ def CMDupload(parser, args): ...@@ -3349,9 +3354,7 @@ def CMDupload(parser, args):
options.squash = ((settings.GetSquashGerritUploads() or options.squash) and options.squash = ((settings.GetSquashGerritUploads() or options.squash) and
not options.no_squash) not options.no_squash)
ret = GerritUpload(options, args, cl, change) ret = cl.CMDUploadChange(options, args, change)
else:
ret = RietveldUpload(options, args, cl, change)
if not ret: if not ret:
git_set_branch_value('last-upload-hash', git_set_branch_value('last-upload-hash',
RunGit(['rev-parse', 'HEAD']).strip()) RunGit(['rev-parse', 'HEAD']).strip())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment