| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1608,10 +1608,11 @@ class Changelist(object):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      self.SetWatchers(watchlist.GetWatchersForPaths(files))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if not options.bypass_hooks:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if options.reviewers or options.add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if options.reviewers or options.tbrs or options.add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # Set the reviewer list now so that presubmit checks can access it.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change_description = ChangeDescription(change.FullDescriptionText())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change_description.update_reviewers(options.reviewers,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                            options.tbrs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                            options.add_owners_to,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                            change)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change.SetDescriptionText(change_description.description)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -2217,9 +2218,8 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          message = options.title + '\n\n' + message
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      change_desc = ChangeDescription(message)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if options.reviewers or options.add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change_desc.update_reviewers(options.reviewers,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                     options.add_owners_to,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                     change)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change_desc.update_reviewers(options.reviewers, options.tbrs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                     options.add_owners_to, change)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if not options.force:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        change_desc.prompt(bug=options.bug, git_footer=False)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -2927,9 +2927,9 @@ class _GerritChangelistImpl(_ChangelistCodereviewBase):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'single commit.')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      confirm_or_exit(action='upload')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if options.reviewers or options.add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      change_desc.update_reviewers(options.reviewers, options.add_owners_to,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                   change)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if options.reviewers or options.tbrs or options.add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      change_desc.update_reviewers(options.reviewers, options.tbrs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                   options.add_owners_to, change)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # Extra options that can be specified at push time. Doc:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # https://gerrit-review.googlesource.com/Documentation/user-upload.html
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -3247,13 +3247,32 @@ class ChangeDescription(object):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      lines.pop(-1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    self._description_lines = lines
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  def update_reviewers(self, reviewers, add_owners_to=None, change=None):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """Rewrites the R=/TBR= line(s) as a single line each."""
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  def update_reviewers(self, reviewers, tbrs, add_owners_to=None, change=None):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """Rewrites the R=/TBR= line(s) as a single line each.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    Args:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      reviewers (list(str)) - list of additional emails to use for reviewers.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      tbrs (list(str)) - list of additional emails to use for TBRs.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      add_owners_to (None|'R'|'TBR') - Pass to do an OWNERS lookup for files in
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        the change that are missing OWNER coverage. If this is not None, you
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        must also pass a value for `change`.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      change (Change) - The Change that should be used for OWNERS lookups.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    assert isinstance(reviewers, list), reviewers
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    assert isinstance(tbrs, list), tbrs
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    assert add_owners_to in (None, 'TBR', 'R'), add_owners_to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if not reviewers and not add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    assert not add_owners_to or not change, add_owners_to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if not reviewers and not tbrs and not add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    reviewers = reviewers[:]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    reviewers = set(reviewers)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tbrs = set(tbrs)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    LOOKUP = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'TBR': tbrs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'R': reviewers,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # Get the set of R= and TBR= lines and remove them from the desciption.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    regexp = re.compile(self.R_LINE)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -3263,34 +3282,27 @@ class ChangeDescription(object):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    self.set_description(new_desc)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # Construct new unified R= and TBR= lines.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    r_names = []
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tbr_names = []
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # First, update tbrs/reviewers with names from the R=/TBR= lines (if any).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for match in matches:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if not match:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        continue
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      people = cleanup_list([match.group(2).strip()])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if match.group(1) == 'TBR':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        tbr_names.extend(people)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        r_names.extend(people)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for name in r_names:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if name not in reviewers:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        reviewers.append(name)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      LOOKUP[match.group(1)].update(cleanup_list([match.group(2).strip()]))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # Next, maybe fill in OWNERS coverage gaps to either tbrs/reviewers.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if add_owners_to:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      owners_db = owners.Database(change.RepositoryRoot(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                  fopen=file, os_path=os.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      all_reviewers = set(tbr_names + reviewers)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      missing_files = owners_db.files_not_covered_by(change.LocalPaths(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                                     all_reviewers)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      names = owners_db.reviewers_for(missing_files, change.author_email)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                                     (tbrs + reviewers))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      LOOKUP[add_owners_to].update(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        owners_db.reviewers_for(missing_files, change.author_email))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        'TBR': tbr_names,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        'R': reviewers,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }[add_owners_to].extend(names)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # If any folks ended up in both groups, remove them from tbrs.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tbrs -= reviewers
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    new_r_line = 'R=' + ', '.join(reviewers) if reviewers else None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    new_tbr_line = 'TBR=' + ', '.join(tbr_names) if tbr_names else None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    new_r_line = 'R=' + ', '.join(sorted(reviewers)) if reviewers else None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    new_tbr_line = 'TBR=' + ', '.join(sorted(tbrs)) if tbrs else None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    # Put the new lines in the description where the old first R= line was.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    line_loc = next((i for i, match in enumerate(matches) if match), -1)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -4711,6 +4723,9 @@ def CMDupload(parser, args):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  parser.add_option('-r', '--reviewers',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    action='append', default=[],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    help='reviewer email addresses')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  parser.add_option('--tbrs',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    action='append', default=[],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    help='TBR email addresses')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  parser.add_option('--cc',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    action='append', default=[],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    help='cc email addresses')
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -4763,6 +4778,7 @@ def CMDupload(parser, args):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return 1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  options.reviewers = cleanup_list(options.reviewers)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  options.tbrs = cleanup_list(options.tbrs)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  options.cc = cleanup_list(options.cc)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if options.message_file:
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -4927,7 +4943,7 @@ def CMDland(parser, args):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  # the commit viewvc url.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if cl.GetIssue():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    change_desc.update_reviewers(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        get_approving_reviewers(cl.GetIssueProperties()))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        get_approving_reviewers(cl.GetIssueProperties()), [])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  commit_desc = ChangeDescription(change_desc.description)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if cl.GetIssue():
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |