def main(self, branch_name=None, *args): """Run the command.""" self.cmd_args = list(args) if branch_name: self.cmd_args.insert(0, branch_name) repository_info, self.tool = self.initialize_scm_tool( client_name=self.options.repository_type) server_url = self.get_server_url(repository_info, self.tool) api_client, api_root = self.get_api(server_url) self.setup_tool(self.tool, api_root=api_root) # Check if repository info on reviewboard server match local ones. repository_info = repository_info.find_server_repository_info(api_root) if (not self.tool.can_merge or not self.tool.can_push_upstream or not self.tool.can_delete_branch): raise CommandError('This command does not support %s repositories.' % self.tool.name) if self.tool.has_pending_changes(): raise CommandError('Working directory is not clean.') if not self.options.destination_branch: raise CommandError('Please specify a destination branch.') if self.options.rid: is_local = branch_name is not None review_request_id = self.options.rid else: review_request = guess_existing_review_request( repository_info, self.options.repository_name, api_root, api_client, self.tool, get_revisions(self.tool, self.cmd_args), guess_summary=False, guess_description=False, is_fuzzy_match_func=self._ask_review_request_match) if not review_request or not review_request.id: raise CommandError('Could not determine the existing review ' 'request URL to land.') review_request_id = review_request.id is_local = True review_request = get_review_request(review_request_id, api_root) if self.options.is_local is not None: is_local = self.options.is_local if is_local: if branch_name is None: branch_name = self.tool.get_current_branch() if branch_name == self.options.destination_branch: raise CommandError('The local branch cannot be merged onto ' 'itself. Try a different local branch or ' 'destination branch.') else: branch_name = None land_error = self.can_land(review_request) if land_error is not None: raise CommandError('Cannot land review request %s: %s' % (review_request_id, land_error)) if self.options.recursive: # The dependency graph shows us which review requests depend on # which other ones. What we are actually after is the order to land # them in, which is the topological sorting order of the converse # graph. It just so happens that if we reverse the topological sort # of a graph, it is a valid topological sorting of the converse # graph, so we don't have to compute the converse graph. dependency_graph = review_request.build_dependency_graph() dependencies = toposort(dependency_graph)[1:] if dependencies: print('Recursively landing dependencies of review request %s.' % review_request_id) for dependency in dependencies: land_error = self.can_land(dependency) if land_error is not None: raise CommandError( 'Aborting recursive land of review request %s.\n' 'Review request %s cannot be landed: %s' % (review_request_id, dependency.id, land_error)) for dependency in reversed(dependencies): self.land(self.options.destination_branch, dependency, None, self.options.squash, self.options.edit, self.options.delete_branch, self.options.dry_run) self.land(self.options.destination_branch, review_request, branch_name, self.options.squash, self.options.edit, self.options.delete_branch, self.options.dry_run) if self.options.push: print('Pushing branch "%s" upstream' % self.options.destination_branch) if not self.options.dry_run: try: self.tool.push_upstream(self.options.destination_branch) except PushError as e: raise CommandError(six.text_type(e))
def main(self, branch_name=None, *args): """Run the command.""" self.cmd_args = list(args) if branch_name: self.cmd_args.insert(0, branch_name) if not self.tool.can_merge: raise CommandError( 'This command does not support %s repositories.' % self.tool.name) if self.options.push and not self.tool.can_push_upstream: raise CommandError('--push is not supported for %s repositories.' % self.tool.name) if self.tool.has_pending_changes(): raise CommandError('Working directory is not clean.') if not self.options.destination_branch: raise CommandError('Please specify a destination branch.') if not self.tool.can_squash_merges: # If the client doesn't support squashing, then never squash. self.options.squash = False if self.options.rid: is_local = branch_name is not None review_request_id = self.options.rid else: try: review_request = guess_existing_review_request( api_root=self.api_root, api_client=self.api_client, tool=self.tool, revisions=get_revisions(self.tool, self.cmd_args), guess_summary=False, guess_description=False, is_fuzzy_match_func=self._ask_review_request_match, repository_id=self.repository.id) except ValueError as e: raise CommandError(six.text_type(e)) if not review_request or not review_request.id: raise CommandError('Could not determine the existing review ' 'request URL to land.') review_request_id = review_request.id is_local = True try: review_request = self.api_root.get_review_request( review_request_id=review_request_id) except APIError as e: raise CommandError('Error getting review request %s: %s' % (review_request_id, e)) if self.options.is_local is not None: is_local = self.options.is_local if is_local: if branch_name is None: branch_name = self.tool.get_current_branch() if branch_name == self.options.destination_branch: raise CommandError('The local branch cannot be merged onto ' 'itself. Try a different local branch or ' 'destination branch.') else: branch_name = None land_error = self.can_land(review_request) if land_error is not None: raise CommandError('Cannot land review request %s: %s' % (review_request_id, land_error)) land_kwargs = { 'delete_branch': self.options.delete_branch, 'destination_branch': self.options.destination_branch, 'dry_run': self.options.dry_run, 'edit': self.options.edit, 'squash': self.options.squash, } self.json.add('landed_review_requests', []) if self.options.recursive: # The dependency graph shows us which review requests depend on # which other ones. What we are actually after is the order to land # them in, which is the topological sorting order of the converse # graph. It just so happens that if we reverse the topological sort # of a graph, it is a valid topological sorting of the converse # graph, so we don't have to compute the converse graph. dependency_graph = review_request.build_dependency_graph() dependencies = toposort(dependency_graph)[1:] if dependencies: self.stdout.write('Recursively landing dependencies of ' 'review request %s.' % review_request_id) for dependency in dependencies: land_error = self.can_land(dependency) if land_error is not None: raise CommandError( 'Aborting recursive land of review request %s.\n' 'Review request %s cannot be landed: %s' % (review_request_id, dependency.id, land_error)) for dependency in reversed(dependencies): self.land(review_request=dependency, **land_kwargs) self.land(review_request=review_request, source_branch=branch_name, **land_kwargs) if self.options.push: self.stdout.write('Pushing branch "%s" upstream' % self.options.destination_branch) if not self.options.dry_run: try: self.tool.push_upstream(self.options.destination_branch) except PushError as e: raise CommandError(six.text_type(e))