Example #1
0
 def test_update_reviewers(self):
     data = [
         ('foo', [], 'foo'),
         ('foo\nR=xx', [], 'foo\nR=xx'),
         ('foo\nTBR=xx', [], 'foo\nTBR=xx'),
         ('foo', ['a@c'], 'foo\n\nR=a@c'),
         ('foo\nR=xx', ['a@c'], 'foo\n\nR=a@c, xx'),
         ('foo\nTBR=xx', ['a@c'], 'foo\n\nR=a@c\nTBR=xx'),
         ('foo\nTBR=xx\nR=yy', ['a@c'], 'foo\n\nR=a@c, yy\nTBR=xx'),
         ('foo\nBUG=', ['a@c'], 'foo\nBUG=\nR=a@c'),
         ('foo\nR=xx\nTBR=yy\nR=bar', ['a@c'],
          'foo\n\nR=a@c, xx, bar\nTBR=yy'),
         ('foo', ['a@c', 'b@c'], 'foo\n\nR=a@c, b@c'),
         ('foo\nBar\n\nR=\nBUG=', ['c@c'], 'foo\nBar\n\nR=c@c\nBUG='),
         ('foo\nBar\n\nR=\nBUG=\nR=', ['c@c'], 'foo\nBar\n\nR=c@c\nBUG='),
         # Same as the line before, but full of whitespaces.
         (
             'foo\nBar\n\n R = \n BUG = \n R = ',
             ['c@c'],
             'foo\nBar\n\nR=c@c\n BUG =',
         ),
         # Whitespaces aren't interpreted as new lines.
         ('foo BUG=allo R=joe ', ['c@c'], 'foo BUG=allo R=joe\n\nR=c@c'),
     ]
     expected = [i[2] for i in data]
     actual = []
     for orig, reviewers, _expected in data:
         obj = git_cl.ChangeDescription(orig)
         obj.update_reviewers(reviewers)
         actual.append(obj.description)
     self.assertEqual(expected, actual)
Example #2
0
 def test_update_reviewers(self):
   data = [
     ('foo', [], 'foo'),
     ('foo', ['a@c'], 'foo\n\nR=a@c'),
     ('foo\nBUG=', ['a@c'], 'foo\nBUG=\nR=a@c'),
     ('foo\nR=xx\nTBR=yy\nR=bar', ['a@c'], 'foo\nTBR=a@c'),
     ('foo', ['a@c', 'b@c'], 'foo\n\nR=a@c, b@c'),
   ]
   for orig, reviewers, expected in data:
     obj = git_cl.ChangeDescription(orig)
     obj.update_reviewers(reviewers)
     self.assertEqual(expected, obj.description)
Example #3
0
 def __init__(self, name, issue, patchset, description, files, local_root,
              rietveld_url, needs_upload):
   # Defer the description processing to git_cl.ChangeDescription.
   self._desc = git_cl.ChangeDescription(description)
   self.name = name
   self.issue = int(issue)
   self.patchset = int(patchset)
   self._files = files or  []
   self.patch = None
   self._local_root = local_root
   self.needs_upload = needs_upload
   self.rietveld = gclient_utils.UpgradeToHttps(
       rietveld_url or GetCodeReviewSetting('CODE_REVIEW_SERVER'))
   self._rpc_server = None
Example #4
0
    def _commit_patch(self, pending):
        """Commits the pending patch to the repository.

    Do the checkout and applies the patch.
    """
        try:
            try:
                # Make sure to apply on HEAD.
                pending.revision = None
                pending.apply_patch(self.context, True)
                # Commit it.
                commit_desc = git_cl.ChangeDescription(pending.description)
                if (self.context.server_hooks_missing
                        and self.context.rietveld.email != pending.owner):
                    commit_desc.update_reviewers(pending.reviewers)
                    commit_desc.append_footer('Author: ' + pending.owner)
                commit_desc.append_footer(
                    'Review URL: %s/%s' %
                    (self.context.rietveld.url, pending.issue))
                pending.revision = self.context.checkout.commit(
                    commit_desc.description, pending.owner)
                if not pending.revision:
                    raise base.DiscardPending(pending,
                                              'Failed to commit patch.')

                # Note that the commit succeeded for commit throttling.
                self.recent_commit_timestamps.append(time.time())
                self.recent_commit_timestamps = (
                    self.recent_commit_timestamps[-(self.MAX_COMMIT_BURST +
                                                    1):])

                viewvc_url = self.context.checkout.get_settings('VIEW_VC')
                issue_desc = git_cl.ChangeDescription(pending.description)
                msg = 'Committed: %s' % pending.revision
                if viewvc_url:
                    viewvc_url = '%s%s' % (viewvc_url.rstrip('/'),
                                           pending.revision)
                    msg = 'Committed: %s' % viewvc_url
                    issue_desc.append_footer(msg)

                # Update the CQ dashboard.
                self.context.status.send(
                    pending, {
                        'verification': 'commit',
                        'payload': {
                            'revision': pending.revision,
                            'output': msg,
                            'url': viewvc_url
                        }
                    })

                # Closes the issue on Rietveld.
                # TODO(csharp): Retry if exceptions are encountered.
                try:
                    self.context.rietveld.close_issue(pending.issue)
                    self.context.rietveld.update_description(
                        pending.issue, issue_desc.description)
                    self.context.rietveld.add_comment(
                        pending.issue,
                        'Change committed as %s' % pending.revision)
                except (urllib2.HTTPError, urllib2.URLError) as e:
                    # Ignore AppEngine flakiness.
                    logging.warning('Unable to fully close the issue')
                # And finally remove the issue. If the close_issue() call above failed,
                # it is possible the dashboard will be confused but it is harmless.
                try:
                    self.queue.get(pending.issue)
                except KeyError:
                    logging.error('Internal inconsistency for %d',
                                  pending.issue)
                self.queue.remove(pending.issue)
            except (checkout.PatchApplicationFailed,
                    patch.UnsupportedPatchFormat) as e:
                raise base.DiscardPending(pending, str(e))
            except subprocess2.CalledProcessError as e:
                stdout = getattr(e, 'stdout', None)
                out = 'Failed to apply the patch.'
                if stdout:
                    out += '\n%s' % stdout
                raise base.DiscardPending(pending, out)
        except base.DiscardPending as e:
            self._discard_pending(e.pending, e.status)
        except Exception as e:
            traceback.print_exc()
            # Swallow every exception in that code and move on. Make sure to send a
            # stack trace though.
            errors.send_stack(e)
Example #5
0
def CMDcommit(change_info, args):
  """Commits the changelist to the repository."""
  if not change_info.GetFiles():
    print "Nothing to commit, changelist is empty."
    return 1

  # OptionallyDoPresubmitChecks has a side-effect which eats these flags.
  bypassed = '--no_presubmit' in args or '--force' in args
  output = OptionallyDoPresubmitChecks(change_info, True, args)
  if not output.should_continue():
    return 1

  # We face a problem with svn here: Let's say change 'bleh' modifies
  # svn:ignore on dir1\. but another unrelated change 'pouet' modifies
  # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*.
  # The only fix is to use --non-recursive but that has its issues too:
  # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise
  # you'll get "svn: Cannot non-recursively commit a directory deletion of a
  # directory with child nodes". Yay...
  commit_cmd = ["svn", "commit"]
  if change_info.issue:
    # Get the latest description from Rietveld.
    change_info.UpdateDescriptionFromIssue()

  change_info.update_reviewers(change_info.GetApprovingReviewers())

  commit_desc = git_cl.ChangeDescription(change_info.description)
  if change_info.issue:
    server = change_info.rietveld
    if not server.startswith("http://") and not server.startswith("https://"):
      server = "http://" + server
    commit_desc.append_footer('Review URL: %s/%d' % (server, change_info.issue))

  handle, commit_filename = tempfile.mkstemp(text=True)
  os.write(handle, commit_desc.description)
  os.close(handle)
  try:
    handle, targets_filename = tempfile.mkstemp(text=True)
    os.write(handle, "\n".join(change_info.GetFileNames()))
    os.close(handle)
    try:
      commit_cmd += ['--file=' + commit_filename]
      commit_cmd += ['--targets=' + targets_filename]
      # Change the current working directory before calling commit.
      output = ''
      try:
        output = RunShell(commit_cmd, True)
      except subprocess2.CalledProcessError, e:
        ErrorExit('Commit failed.\n%s' % e)
    finally:
      os.remove(commit_filename)
  finally:
    os.remove(targets_filename)
  if output.find("Committed revision") != -1:
    change_info.Delete()

    if change_info.issue:
      revision = re.compile(".*?\nCommitted revision (\d+)",
                            re.DOTALL).match(output).group(1)
      viewvc_url = GetCodeReviewSetting('VIEW_VC')
      if viewvc_url and revision:
        change_info.append_footer('Committed: ' + viewvc_url + revision)
      elif revision:
        change_info.append_footer('Committed: ' + revision)
      change_info.CloseIssue()
      props = change_info.RpcServer().get_issue_properties(
          change_info.issue, False)
      patch_num = len(props['patchsets'])
      comment = "Committed patchset #%d manually as r%s" % (patch_num, revision)
      comment += ' (presubmit successful).' if not bypassed else '.'
      change_info.AddComment(comment)
  return 0
Example #6
0
 def UpdateDescriptionFromIssue(self):
   """Updates self.description with the issue description from Rietveld."""
   self._desc = git_cl.ChangeDescription(self.GetIssueDescription())
Example #7
0
 def force_description(self, new_description):
   self._desc = git_cl.ChangeDescription(new_description)
   self.needs_upload = True