| OLD | NEW |
| 1 # coding=utf8 | 1 # coding=utf8 |
| 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 """Commit queue manager class. | 5 """Commit queue manager class. |
| 6 | 6 |
| 7 Security implications: | 7 Security implications: |
| 8 | 8 |
| 9 The following hypothesis are made: | 9 The following hypothesis are made: |
| 10 - Commit queue: | 10 - Commit queue: |
| 11 - Impersonate the same svn credentials that the patchset owner. | 11 - Impersonate the same svn credentials that the patchset owner. |
| 12 - Can't impersonate a non committer. | 12 - Can't impersonate a non committer. |
| 13 - SVN will check the committer write access. | 13 - SVN will check the committer write access. |
| 14 """ | 14 """ |
| 15 | 15 |
| 16 import errno |
| 16 import logging | 17 import logging |
| 17 import os | 18 import os |
| 19 import socket |
| 20 import ssl |
| 18 import time | 21 import time |
| 19 import traceback | 22 import traceback |
| 20 import urllib2 | 23 import urllib2 |
| 21 | 24 |
| 22 import find_depot_tools # pylint: disable=W0611 | 25 import find_depot_tools # pylint: disable=W0611 |
| 23 import checkout | 26 import checkout |
| 24 import git_cl | 27 import git_cl |
| 25 import patch | 28 import patch |
| 26 import ssl | |
| 27 import subprocess2 | 29 import subprocess2 |
| 28 | 30 |
| 29 import errors | 31 import errors |
| 30 import model | 32 import model |
| 31 from verification import base | 33 from verification import base |
| 32 | 34 |
| 33 | 35 |
| 34 class PendingCommit(base.Verified): | 36 class PendingCommit(base.Verified): |
| 35 """Represents a pending commit that is being processed.""" | 37 """Represents a pending commit that is being processed.""" |
| 36 # Important since they tell if we need to revalidate and send try jobs | 38 # Important since they tell if we need to revalidate and send try jobs |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 pending, | 188 pending, |
| 187 { 'verification': 'abort', | 189 { 'verification': 'abort', |
| 188 'payload': { | 190 'payload': { |
| 189 'output': 'CQ bit was unchecked on CL. Ignoring.' }}) | 191 'output': 'CQ bit was unchecked on CL. Ignoring.' }}) |
| 190 pending.get_state = lambda: base.IGNORED | 192 pending.get_state = lambda: base.IGNORED |
| 191 self._discard_pending(pending, None) | 193 self._discard_pending(pending, None) |
| 192 | 194 |
| 193 # Find new issues. | 195 # Find new issues. |
| 194 for issue_id in new_issues: | 196 for issue_id in new_issues: |
| 195 if str(issue_id) not in self.queue.pending_commits: | 197 if str(issue_id) not in self.queue.pending_commits: |
| 196 issue_data = self.context.rietveld.get_issue_properties( | 198 try: |
| 197 issue_id, True) | 199 issue_data = self.context.rietveld.get_issue_properties( |
| 200 issue_id, True) |
| 201 except urllib2.HTTPError as e: |
| 202 if e.code in (500, 502, 503): |
| 203 # Temporary AppEngine hiccup. Just log it and continue. |
| 204 logging.warning('%s while accessing %s. Ignoring error.' % ( |
| 205 str(e), e.url)) |
| 206 continue |
| 207 raise |
| 208 except urllib2.URLError as e: |
| 209 # Temporary AppEngine hiccup. Just log it and continue. |
| 210 if 'timed out' in e.reason: |
| 211 logging.warning( |
| 212 '%s while accessing rietveld issue %s. Ignoring error.' % ( |
| 213 str(e), str(issue_id))) |
| 214 continue |
| 215 raise |
| 216 except socket.error as e: |
| 217 # Temporary AppEngine hiccup. Just log it and continue. |
| 218 if e.errno == errno.ECONNRESET: |
| 219 logging.warning( |
| 220 '%s while accessing rietveld issue %s. Ignoring error.' % ( |
| 221 str(e), str(issue_id))) |
| 222 continue |
| 223 raise |
| 224 except IOError as e: |
| 225 # Temporary AppEngine hiccup. Just log it and continue. |
| 226 if e.errno == 'socket error': |
| 227 logging.warning( |
| 228 '%s while accessing rietveld issue %s. Ignoring error.' % ( |
| 229 str(e), str(issue_id))) |
| 230 continue |
| 231 raise |
| 198 # This assumption needs to hold. | 232 # This assumption needs to hold. |
| 199 assert issue_id == issue_data['issue'] | 233 assert issue_id == issue_data['issue'] |
| 200 if issue_data['patchsets'] and issue_data['commit']: | 234 if issue_data['patchsets'] and issue_data['commit']: |
| 201 logging.info('Found new issue %d' % issue_id) | 235 logging.info('Found new issue %d' % issue_id) |
| 202 self.queue.add( | 236 self.queue.add( |
| 203 PendingCommit( | 237 PendingCommit( |
| 204 issue=issue_id, | 238 issue=issue_id, |
| 205 owner=issue_data['owner_email'], | 239 owner=issue_data['owner_email'], |
| 206 reviewers=issue_data['reviewers'], | 240 reviewers=issue_data['reviewers'], |
| 207 patchset=issue_data['patchsets'][-1], | 241 patchset=issue_data['patchsets'][-1], |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 """Loads the commit queue state from a JSON file.""" | 561 """Loads the commit queue state from a JSON file.""" |
| 528 self.queue = model.load_from_json_file(filename) | 562 self.queue = model.load_from_json_file(filename) |
| 529 | 563 |
| 530 def save(self, filename): | 564 def save(self, filename): |
| 531 """Save the commit queue state in a simple JSON file.""" | 565 """Save the commit queue state in a simple JSON file.""" |
| 532 model.save_to_json_file(filename, self.queue) | 566 model.save_to_json_file(filename, self.queue) |
| 533 | 567 |
| 534 def close(self): | 568 def close(self): |
| 535 """Close all the active pending manager items.""" | 569 """Close all the active pending manager items.""" |
| 536 self.context.status.close() | 570 self.context.status.close() |
| OLD | NEW |